From 8fa2a49a8327f1a88f3d2557e22eb85ee2dcb235 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Mon, 24 Aug 2026 10:50:01 +0200 Subject: [PATCH 1/6] Rename .java to .kt Signed-off-by: tobiasKaminsky --- .../{ReadFileRemoteOperation.java => ReadFileRemoteOperation.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename library/src/main/java/com/owncloud/android/lib/resources/files/{ReadFileRemoteOperation.java => ReadFileRemoteOperation.kt} (100%) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt similarity index 100% rename from library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.java rename to library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt From 2ca59190de35b037f8736e1a04505fdf5b2f1b35 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Mon, 24 Aug 2026 10:50:01 +0200 Subject: [PATCH 2/6] wip Signed-off-by: tobiasKaminsky --- gradle/verification-metadata.xml | 8 + library/build.gradle | 2 +- .../files/ReadFileRemoteOperationIT.kt | 29 +- .../files/UploadFileRemoteOperationIT.kt | 6 +- .../java/com/nextcloud/common/DavResponse.kt | 39 +++ .../common/NextcloudAuthenticator.kt | 50 +++ .../com/nextcloud/common/NextcloudClient.kt | 8 + .../nextcloud/operations/PropFindMethod2.kt | 11 + .../nextcloud/operations/PropFindResult.kt | 21 ++ .../owncloud/android/lib/common/DavMethod.kt | 29 ++ .../lib/common/network/ExtendedProperties.kt | 60 ++++ .../android/lib/common/network/WebdavEntry.kt | 5 +- .../lib/common/network/WebdavUtils.java | 6 +- .../lib/common/network/WebdavUtils2.kt | 286 ++++++++++++++++++ .../lib/common/utils/WebDavFileUtils2.kt | 180 +++++++++++ .../files/ReadFileRemoteOperation.kt | 174 ++++++----- .../lib/resources/files/model/RemoteFile.kt | 18 +- .../resources/files/webdav/NCCreationTime.kt | 28 ++ .../lib/resources/files/webdav/NCEncrypted.kt | 41 +++ .../lib/resources/files/webdav/NCEtag.kt | 33 ++ .../lib/resources/files/webdav/NCFavorite.kt | 41 +++ .../files/webdav/NCGetLastModified.kt | 36 +++ .../lib/resources/files/webdav/NCHidden.kt | 41 +++ .../lib/resources/files/webdav/NCLock.kt | 41 +++ .../lib/resources/files/webdav/NCLockOwner.kt | 41 +++ .../files/webdav/NCLockOwnerDisplayName.kt | 41 +++ .../files/webdav/NCLockOwnerEditor.kt | 42 +++ .../resources/files/webdav/NCLockOwnerType.kt | 42 +++ .../lib/resources/files/webdav/NCLockTime.kt | 31 ++ .../resources/files/webdav/NCLockTimeout.kt | 41 +++ .../lib/resources/files/webdav/NCLockToken.kt | 41 +++ .../resources/files/webdav/NCMetadataGPS.kt | 44 +++ .../files/webdav/NCMetadataLivePhoto.kt | 41 +++ .../files/webdav/NCMetadataPhotosGPS.kt | 61 ++++ .../files/webdav/NCMetadataPhotosSize.kt | 61 ++++ .../resources/files/webdav/NCMetadataSize.kt | 44 +++ .../lib/resources/files/webdav/NCMountType.kt | 37 +++ .../lib/resources/files/webdav/NCNote.kt | 41 +++ .../resources/files/webdav/NCPermissions.kt | 41 +++ .../lib/resources/files/webdav/NCPreview.kt | 41 +++ .../resources/files/webdav/NCRichWorkspace.kt | 41 +++ .../lib/resources/files/webdav/NCSharees.kt | 118 ++++++++ .../lib/resources/files/webdav/NCTags.kt | 104 +++++++ .../files/webdav/NCTrashbinDeletionTime.kt | 41 +++ .../files/webdav/NCTrashbinFilename.kt | 41 +++ .../files/webdav/NCTrashbinLocation.kt | 41 +++ .../resources/files/webdav/NCUploadTime.kt | 41 +++ .../files/webdav/OCCommentsUnread.kt | 41 +++ .../resources/files/webdav/OCDisplayName.kt | 41 +++ .../lib/resources/files/webdav/OCId.kt | 41 +++ .../lib/resources/files/webdav/OCLocalId.kt | 41 +++ .../files/webdav/OCOwnerDisplayName.kt | 41 +++ .../lib/resources/files/webdav/OCOwnerId.kt | 41 +++ .../lib/resources/files/webdav/OCSize.kt | 41 +++ .../nextcloud/common/NextcloudClientTest.kt | 2 +- 55 files changed, 2490 insertions(+), 109 deletions(-) create mode 100644 library/src/main/java/com/nextcloud/common/DavResponse.kt create mode 100644 library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt create mode 100644 library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt create mode 100644 library/src/main/java/com/nextcloud/operations/PropFindResult.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3c9e98b4e..2b4342e0c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -8637,6 +8637,14 @@ + + + + + + + + diff --git a/library/build.gradle b/library/build.gradle index 5512aa552..54df040b3 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -64,7 +64,7 @@ dependencies { implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5' api 'com.squareup.okhttp3:okhttp:5.5.0' - implementation 'com.github.bitfireAT:dav4jvm:3.0.2' + implementation 'com.github.bitfireAT:dav4jvm:2.1.3' // in transition phase, we use old and new libs implementation group: 'com.google.code.gson', name: 'gson', version: '2.14.0' implementation 'androidx.annotation:annotation:1.10.0' 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..3c430d77a 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 @@ -12,7 +12,6 @@ import com.owncloud.android.lib.common.OwnCloudClientManagerFactory import com.owncloud.android.lib.resources.e2ee.ToggleEncryptionRemoteOperation 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.status.GetCapabilitiesRemoteOperation import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertEquals @@ -23,14 +22,17 @@ import org.junit.Test class ReadFileRemoteOperationIT : AbstractIT() { @Test fun readRemoteFolder() { - val remotePath = "/test/" + val remotePath = "/folder/" assertTrue(CreateFolderRemoteOperation(remotePath, true).execute(client).isSuccess) - val result = ReadFileRemoteOperation(remotePath).execute(client) - + var result = ReadFileRemoteOperation(remotePath).execute(client) + assertTrue(result.isSuccess) + assertEquals(remotePath, result.resultData.remotePath) + + result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) - assertEquals(remotePath, (result.data[0] as RemoteFile).remotePath) + assertEquals(remotePath, result.resultData.remotePath) } @Test @@ -70,11 +72,11 @@ class ReadFileRemoteOperationIT : AbstractIT() { val movieFileResult = ReadFileRemoteOperation(movieFilePath).execute(client) assertTrue(movieFileResult.isSuccess) - val movieRemoteFile = movieFileResult.data[0] as RemoteFile + val movieRemoteFile = movieFileResult.resultData val livePhotoResult = ReadFileRemoteOperation(livePhotoPath).execute(client) assertTrue(livePhotoResult.isSuccess) - val livePhotoRemoteFile = livePhotoResult.data[0] as RemoteFile + val livePhotoRemoteFile = livePhotoResult.resultData assertEquals(livePhotoRemoteFile.livePhoto, movieRemoteFile.remotePath) assertTrue(movieRemoteFile.hidden) @@ -91,10 +93,13 @@ class ReadFileRemoteOperationIT : AbstractIT() { .isSuccess ) - val result = ReadFileRemoteOperation(remotePath).execute(client) + var result = ReadFileRemoteOperation(remotePath).execute(client) + assertTrue(result.isSuccess) + assertEquals(remotePath, result.resultData.remotePath) + result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) - assertEquals(remotePath, (result.data[0] as RemoteFile).remotePath) + assertEquals(remotePath, result.resultData.remotePath) } @Test @@ -111,7 +116,7 @@ class ReadFileRemoteOperationIT : AbstractIT() { val result = ReadFileRemoteOperation(remotePath).execute(client) assertTrue(result.isSuccess) - val remoteFile = result.data[0] as RemoteFile + val remoteFile = result.resultData @Suppress("Detekt.MagicNumber") if (isServerAtLeast(NextcloudVersion.nextcloud_23)) { @@ -142,7 +147,7 @@ class ReadFileRemoteOperationIT : AbstractIT() { assertTrue(CreateFolderRemoteOperation(remotePath, true).execute(client).isSuccess) var result = ReadFileRemoteOperation(remotePath).execute(client) - val remoteFile = result.data[0] as RemoteFile + val remoteFile = result.resultData assertTrue(result.isSuccess) assertFalse(remoteFile.isEncrypted) @@ -160,6 +165,6 @@ class ReadFileRemoteOperationIT : AbstractIT() { // re-read result = ReadFileRemoteOperation(remotePath).execute(client) - assertEquals(true, (result.data[0] as RemoteFile).isEncrypted) + assertEquals(true, result.resultData.isEncrypted) } } 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..43f933fa3 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 @@ -66,10 +66,10 @@ class UploadFileRemoteOperationIT : AbstractIT() { ) // ReadFolderRemoteOperation - result = ReadFolderRemoteOperation(remotePath).execute(client) - assertTrue(result.isSuccess) + var result2 = ReadFolderRemoteOperation(remotePath).execute(client) + assertTrue(result2.isSuccess) - remoteFile = result.data[0] as RemoteFile + remoteFile = result2.data[0] as RemoteFile assertEquals(remotePath, remoteFile.remotePath) assertEquals(creationTimestamp, remoteFile.creationTimestamp) diff --git a/library/src/main/java/com/nextcloud/common/DavResponse.kt b/library/src/main/java/com/nextcloud/common/DavResponse.kt new file mode 100644 index 000000000..5ef3a0846 --- /dev/null +++ b/library/src/main/java/com/nextcloud/common/DavResponse.kt @@ -0,0 +1,39 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.common + +import okhttp3.Headers +import okhttp3.internal.http.StatusLine + +/** + * Encapsulates essential data returned as responses from various DAV calls. + */ +data class DavResponse( + var success: Boolean = false, + var status: StatusLine? = null, + var headers: Headers? = null +) { + /** + * Return value of specified header. + * + * Simple helper to aid with nullability when called from Java. + * + * @param key name of header to get + * @return value of header or `null` when header is not set + */ + fun getHeader(key: String): String? = headers?.get(key) + + /** + * Return value of status code. + * + * Simple helper to aid with nullability when called from Java. + * + * @return HTTP status code or `0` if not set. + */ + fun getStatusCode(): Int = status?.code ?: 0 +} diff --git a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt new file mode 100644 index 000000000..139fd5e4e --- /dev/null +++ b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt @@ -0,0 +1,50 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2022 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ +package com.nextcloud.common + +import okhttp3.Authenticator +import okhttp3.Request +import okhttp3.Response +import okhttp3.Route + +class NextcloudAuthenticator(private val credentials: String) : Authenticator { + @Suppress("ReturnCount") + override fun authenticate( + route: Route?, + response: Response + ): Request? { + val authenticatorType = "Authorization" + + if (response.request.header(authenticatorType) != null) { + return null + } + + var countedResponse: Response? = response + + var attemptsCount = 0 + + countedResponse = countedResponse?.priorResponse + + while (countedResponse != null) { + attemptsCount++ + if (attemptsCount == MAX_ATTEMPTS) { + return null + } + + countedResponse = countedResponse.priorResponse + } + + return response.request.newBuilder() + .header(authenticatorType, credentials) + .build() + } + + companion object { + const val MAX_ATTEMPTS = 3 + } +} diff --git a/library/src/main/java/com/nextcloud/common/NextcloudClient.kt b/library/src/main/java/com/nextcloud/common/NextcloudClient.kt index 7f51e6437..d4f361744 100644 --- a/library/src/main/java/com/nextcloud/common/NextcloudClient.kt +++ b/library/src/main/java/com/nextcloud/common/NextcloudClient.kt @@ -191,6 +191,14 @@ class NextcloudClient private constructor( return result } + fun disabledRedirectClient(): OkHttpClient { + return client + .newBuilder() + .followRedirects(false) + .authenticator(NextcloudAuthenticator(credentials)) + .build() + } + private fun setRedirectedDestinationHeader( method: OkHttpMethodBase, location: String, diff --git a/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt b/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt new file mode 100644 index 000000000..8309dff0d --- /dev/null +++ b/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt @@ -0,0 +1,11 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.operations + +class PropFindMethod2 { +} diff --git a/library/src/main/java/com/nextcloud/operations/PropFindResult.kt b/library/src/main/java/com/nextcloud/operations/PropFindResult.kt new file mode 100644 index 000000000..d70e7f23d --- /dev/null +++ b/library/src/main/java/com/nextcloud/operations/PropFindResult.kt @@ -0,0 +1,21 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.operations + +import com.nextcloud.common.DavResponse +import com.owncloud.android.lib.resources.files.model.RemoteFile + +data class PropFindResult( + val davResponse: DavResponse = DavResponse(), + var root: RemoteFile = RemoteFile(), + val children: MutableList = mutableListOf() +) { + fun getContent(): List { + return listOf(root) + children + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt b/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt new file mode 100644 index 000000000..68511bd1f --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt @@ -0,0 +1,29 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-FileCopyrightText: 2023 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ +package com.nextcloud.common + +import android.net.Uri +import com.owncloud.android.lib.common.network.WebdavUtils2 +import okhttp3.HttpUrl +import okhttp3.OkHttpClient + +abstract class DavMethod(private val httpUrl: HttpUrl) { + fun execute(nextcloudClient: NextcloudClient): T { + // register custom property + WebdavUtils2.registerCustomFactories() + + return apply(nextcloudClient.disabledRedirectClient(), httpUrl, nextcloudClient.filesDavUri) + } + + abstract fun apply( + client: OkHttpClient, + httpUrl: HttpUrl, + filesDavUri: Uri + ): T +} diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt new file mode 100644 index 000000000..130964f2f --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt @@ -0,0 +1,60 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ +package com.owncloud.android.lib.common.network + +import at.bitfire.dav4jvm.Property + +enum class ExtendedProperties(val value: String, val namespace: String) { + CREATION_TIME("creation_time", WebdavUtils.NAMESPACE_NC), + COMMENTS_READ_MARKER("readMarker", WebdavUtils.NAMESPACE_NC), + DISPLAY_NAME("display-name", WebdavUtils.NAMESPACE_OC), + FAVORITE("favorite", WebdavUtils.NAMESPACE_OC), + HAS_PREVIEW("has-preview", WebdavUtils.NAMESPACE_NC), + HIDDEN("hidden", WebdavUtils.NAMESPACE_NC), + IS_ENCRYPTED("is-encrypted", WebdavUtils.NAMESPACE_NC), + LOCK("lock", WebdavUtils.NAMESPACE_NC), + LOCK_OWNER("lock-owner", WebdavUtils.NAMESPACE_NC), + LOCK_OWNER_DISPLAY_NAME("lock-owner-displayname", WebdavUtils.NAMESPACE_NC), + LOCK_OWNER_EDITOR("lock-owner-editor", WebdavUtils.NAMESPACE_NC), + LOCK_OWNER_TYPE("lock-owner-type", WebdavUtils.NAMESPACE_NC), + LOCK_TIME("lock-time", WebdavUtils.NAMESPACE_NC), + LOCK_TIMEOUT("lock-timeout", WebdavUtils.NAMESPACE_NC), + LOCK_TOKEN("lock-token", WebdavUtils.NAMESPACE_NC), + + @Deprecated("Removed with v28. Use METADATA_PHOTOS_GPS instead.") + METADATA_GPS("file-metadata-gps", WebdavUtils.NAMESPACE_NC), + METADATA_LIVE_PHOTO("metadata-files-live-photo", WebdavUtils.NAMESPACE_NC), + METADATA_PHOTOS_GPS("metadata-photos-gps", WebdavUtils.NAMESPACE_NC), + METADATA_PHOTOS_SIZE("metadata-photos-size", WebdavUtils.NAMESPACE_NC), + + @Deprecated("Removed with v28. Use METADATA_PHOTOS_SIZE instead.") + METADATA_SIZE("file-metadata-size", WebdavUtils.NAMESPACE_NC), + MOUNT_TYPE("mount-type", WebdavUtils.NAMESPACE_NC), + NAME_LOCAL_ID("fileid", WebdavUtils.NAMESPACE_OC), + NAME_PERMISSIONS("permissions", WebdavUtils.NAMESPACE_OC), + NAME_REMOTE_ID("id", WebdavUtils.NAMESPACE_OC), + NAME_SIZE("size", WebdavUtils.NAMESPACE_OC), + NOTE("note", WebdavUtils.NAMESPACE_NC), + OWNER_DISPLAY_NAME("owner-display-name", WebdavUtils.NAMESPACE_OC), + OWNER_ID("owner-id", WebdavUtils.NAMESPACE_OC), + RICH_WORKSPACE("rich-workspace", WebdavUtils.NAMESPACE_NC), + SHAREES("sharees", WebdavUtils.NAMESPACE_NC), + SHAREES_DISPLAY_NAME("display-name", WebdavUtils.NAMESPACE_NC), + SHAREES_ID("id", WebdavUtils.NAMESPACE_NC), + SHAREES_SHARE_TYPE("type", WebdavUtils.NAMESPACE_NC), + SYSTEM_TAGS("system-tags", WebdavUtils.NAMESPACE_NC), + TRASHBIN_DELETION_TIME("trashbin-deletion-time", WebdavUtils.NAMESPACE_NC), + TRASHBIN_FILENAME("trashbin-filename", WebdavUtils.NAMESPACE_NC), + TRASHBIN_ORIGINAL_LOCATION("trashbin-original-location", WebdavUtils.NAMESPACE_NC), + UNREAD_COMMENTS("comments-unread", WebdavUtils.NAMESPACE_OC), + UPLOAD_TIME("upload_time", WebdavUtils.NAMESPACE_NC); + + fun toPropertyName(): Property.Name { + return Property.Name(namespace, value) + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 45178b9ed..eece446f1 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -153,7 +153,7 @@ class WebdavEntry constructor( if (prop != null) { val value = prop.value if (value != null) { - contentType = "DIR" // a specific attribute would be better, + contentType = DIR_TYPE // a specific attribute would be better, // but this is enough; // unless while we have no reason to distinguish // MIME types for folders @@ -613,7 +613,7 @@ class WebdavEntry constructor( fun decodedPath(): String = Uri.decode(path) val isDirectory: Boolean - get() = "DIR" == contentType + get() = DIR_TYPE == contentType private fun resetData() { permissions = null @@ -690,6 +690,7 @@ class WebdavEntry constructor( const val PROPERTY_DATE_RANGE = "dateRange" const val PROPERTY_COLLABORATORS = "collaborators" const val COLLABORATORS_SHARE_LABEL = "label" + const val DIR_TYPE = "DIR" private const val IS_ENCRYPTED = "1" private const val CODE_PROP_NOT_FOUND = 404 } diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java index 338d7fafd..47a250ddd 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java @@ -16,6 +16,8 @@ import android.net.Uri; +import androidx.annotation.Nullable; + import com.nextcloud.common.OkHttpMethodBase; import org.apache.commons.httpclient.Header; @@ -29,11 +31,13 @@ import java.util.Date; import java.util.Locale; -import androidx.annotation.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @SuppressFBWarnings("FS") public class WebdavUtils { + public static String NAMESPACE_OC = "http://owncloud.org/ns"; + public static String NAMESPACE_NC = "http://nextcloud.org/ns"; + private static final SimpleDateFormat DATETIME_FORMATS[] = { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt new file mode 100644 index 000000000..85915e852 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt @@ -0,0 +1,286 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.common.network + +import android.net.Uri +import at.bitfire.dav4jvm.PropertyRegistry.register +import at.bitfire.dav4jvm.property.CreationDate +import at.bitfire.dav4jvm.property.DisplayName +import at.bitfire.dav4jvm.property.GetContentLength +import at.bitfire.dav4jvm.property.GetContentType +import at.bitfire.dav4jvm.property.ResourceType +import com.google.gson.Gson +import com.owncloud.android.lib.resources.files.webdav.NCCreationTime +import com.owncloud.android.lib.resources.files.webdav.NCEncrypted +import com.owncloud.android.lib.resources.files.webdav.NCEtag +import com.owncloud.android.lib.resources.files.webdav.NCFavorite +import com.owncloud.android.lib.resources.files.webdav.NCGetLastModified +import com.owncloud.android.lib.resources.files.webdav.NCHidden +import com.owncloud.android.lib.resources.files.webdav.NCLock +import com.owncloud.android.lib.resources.files.webdav.NCLockOwner +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerDisplayName +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerEditor +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerType +import com.owncloud.android.lib.resources.files.webdav.NCLockTime +import com.owncloud.android.lib.resources.files.webdav.NCLockTimeout +import com.owncloud.android.lib.resources.files.webdav.NCLockToken +import com.owncloud.android.lib.resources.files.webdav.NCMetadataGPS +import com.owncloud.android.lib.resources.files.webdav.NCMetadataLivePhoto +import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosGPS +import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosSize +import com.owncloud.android.lib.resources.files.webdav.NCMetadataSize +import com.owncloud.android.lib.resources.files.webdav.NCMountType +import com.owncloud.android.lib.resources.files.webdav.NCNote +import com.owncloud.android.lib.resources.files.webdav.NCPermissions +import com.owncloud.android.lib.resources.files.webdav.NCPreview +import com.owncloud.android.lib.resources.files.webdav.NCRichWorkspace +import com.owncloud.android.lib.resources.files.webdav.NCSharees +import com.owncloud.android.lib.resources.files.webdav.NCTags +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinDeletionTime +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinFilename +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinLocation +import com.owncloud.android.lib.resources.files.webdav.NCUploadTime +import com.owncloud.android.lib.resources.files.webdav.OCCommentsUnread +import com.owncloud.android.lib.resources.files.webdav.OCDisplayName +import com.owncloud.android.lib.resources.files.webdav.OCId +import com.owncloud.android.lib.resources.files.webdav.OCLocalId +import com.owncloud.android.lib.resources.files.webdav.OCOwnerDisplayName +import com.owncloud.android.lib.resources.files.webdav.OCOwnerId +import com.owncloud.android.lib.resources.files.webdav.OCSize +import org.apache.commons.httpclient.HttpMethod +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +object WebdavUtils2 { + const val NAMESPACE_OC = "http://owncloud.org/ns" + const val NAMESPACE_NC = "http://nextcloud.org/ns" + + internal val gson = Gson() + + private val DATETIME_FORMATS = + arrayOf( + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US), + SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US), + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US), + SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US), + SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), + SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US), + SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.US) + ) + + object PROPERTYSETS { + val ALL = + arrayOf( + DisplayName.NAME, + GetContentType.NAME, + ResourceType.NAME, + GetContentLength.NAME, + NCGetLastModified.NAME, + CreationDate.NAME, + NCEtag.NAME, + NCPermissions.NAME, + OCLocalId.NAME, + OCId.NAME, + OCSize.NAME, + NCFavorite.NAME, + NCEncrypted.NAME, + NCMountType.NAME, + OCOwnerId.NAME, + OCOwnerDisplayName.NAME, + OCCommentsUnread.NAME, + NCPreview.NAME, + NCNote.NAME, + NCSharees.NAME, + NCRichWorkspace.NAME, + NCCreationTime.NAME, + NCUploadTime.NAME, + NCLock.NAME, + NCLockOwnerType.NAME, + NCLockOwner.NAME, + NCLockOwnerDisplayName.NAME, + NCLockOwnerEditor.NAME, + NCLockTime.NAME, + NCLockTimeout.NAME, + NCLockToken.NAME, + NCTags.NAME, + NCMetadataSize.NAME, + NCMetadataGPS.NAME, + NCMetadataSize.NAME, + NCMetadataPhotosSize.NAME, + NCMetadataPhotosGPS.NAME, + NCMetadataLivePhoto.NAME, + NCHidden.NAME + ) + + val FILE = + arrayOf( + DisplayName.NAME, + GetContentType.NAME, + ResourceType.NAME, + GetContentLength.NAME, + NCGetLastModified.NAME, + CreationDate.NAME, + NCEtag.NAME, + NCPermissions.NAME, + OCLocalId.NAME, + OCId.NAME, + OCSize.NAME, + NCFavorite.NAME, + NCPreview.NAME, + NCSharees.NAME, + NCCreationTime.NAME, + NCUploadTime.NAME, + NCLock.NAME, + NCLockOwnerType.NAME, + NCLockOwner.NAME, + NCLockOwnerDisplayName.NAME, + NCLockOwnerEditor.NAME, + NCLockTime.NAME, + NCLockTimeout.NAME, + NCLockToken.NAME, + NCEncrypted.NAME, + NCTags.NAME, + NCMetadataSize.NAME, + NCMetadataGPS.NAME, + NCMetadataPhotosSize.NAME, + NCMetadataPhotosGPS.NAME, + NCMetadataLivePhoto.NAME, + NCHidden.NAME + ) + + val TRASHBIN = + arrayOf( + ResourceType.NAME, + GetContentType.NAME, + GetContentLength.NAME, + OCSize.NAME, + OCId.NAME, + NCTrashbinFilename.NAME, + NCTrashbinLocation.NAME, + NCTrashbinDeletionTime.NAME + ) + + val FILE_VERSION = + arrayOf( + GetContentType.NAME, + ResourceType.NAME, + GetContentLength.NAME, + NCGetLastModified.NAME, + CreationDate.NAME, + OCId.NAME, + OCSize.NAME + ) + + val CHUNK = + arrayOf( + GetContentType.NAME, + ResourceType.NAME, + GetContentLength.NAME + ) + } + + fun parseResponseDate(date: String?): Date? { + for (format in DATETIME_FORMATS) { + try { + date?.let { return format.parse(it) } + } catch (e: ParseException) { + // wrong format + } + } + return null + } + + /** + * Encodes a path according to URI RFC 2396. + * + * + * If the received path doesn't start with "/", the method adds it. + * + * @param remoteFilePath Path + * @return Encoded path according to RFC 2396, always starting with "/" + */ + fun encodePath(remoteFilePath: String?): String { + val encodedPath = Uri.encode(remoteFilePath, "/") + if (!encodedPath.startsWith("/")) { + return "/$encodedPath" + } + return encodedPath + } + + fun parseEtag(etag: String?): String { + if (etag.isNullOrEmpty()) { + return "" + } + return etag.removeSuffix("-gzip").removeSurrounding("\"") + } + + fun getEtagFromResponse(method: HttpMethod): String { + var eTag = method.getResponseHeader("OC-ETag") + if (eTag == null) { + eTag = method.getResponseHeader("oc-etag") + } + if (eTag == null) { + eTag = method.getResponseHeader("ETag") + } + if (eTag == null) { + eTag = method.getResponseHeader("etag") + } + if (eTag != null) { + return parseEtag(eTag.value) + } + return "" + } + + fun registerCustomFactories() { + val list = + listOf( + NCCreationTime.Factory(), + NCEncrypted.Factory(), + NCEtag.Factory(), + NCFavorite.Factory(), + NCGetLastModified.Factory(), + NCHidden.Factory(), + NCLock.Factory(), + NCLockOwnerDisplayName.Factory(), + NCLockOwnerEditor.Factory(), + NCLockOwner.Factory(), + NCLockOwnerType.Factory(), + NCLockTime.Factory(), + NCLockTimeout.Factory(), + NCLockToken.Factory(), + NCMetadataGPS.Factory(), + NCMetadataLivePhoto.Factory(), + NCMetadataPhotosGPS.Factory(), + NCMetadataPhotosSize.Factory(), + NCMetadataSize.Factory(), + NCMountType.Factory(), + NCNote.Factory(), + NCPermissions.Factory(), + NCPreview.Factory(), + NCRichWorkspace.Factory(), + NCSharees.Factory(), + NCTags.Factory(), + NCTrashbinDeletionTime.Factory(), + NCTrashbinFilename.Factory(), + NCTrashbinLocation.Factory(), + NCUploadTime.Factory(), + OCCommentsUnread.Factory(), + OCDisplayName.Factory(), + OCId.Factory(), + OCLocalId.Factory(), + OCOwnerDisplayName.Factory(), + OCOwnerId.Factory(), + OCSize.Factory() + ) + register(list) + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt b/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt new file mode 100644 index 000000000..cbb59085e --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt @@ -0,0 +1,180 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2017 Mario Danic + * SPDX-License-Identifier: MIT + */ +package com.owncloud.android.lib.common.utils + +import android.net.Uri +import at.bitfire.dav4jvm.Response +import at.bitfire.dav4jvm.property.DisplayName +import at.bitfire.dav4jvm.property.GetContentLength +import at.bitfire.dav4jvm.property.GetContentType +import at.bitfire.dav4jvm.property.ResourceType +import com.owncloud.android.lib.common.network.WebdavEntry +import com.owncloud.android.lib.resources.files.model.RemoteFile +import com.owncloud.android.lib.resources.files.webdav.NCCreationTime +import com.owncloud.android.lib.resources.files.webdav.NCEncrypted +import com.owncloud.android.lib.resources.files.webdav.NCEtag +import com.owncloud.android.lib.resources.files.webdav.NCFavorite +import com.owncloud.android.lib.resources.files.webdav.NCGetLastModified +import com.owncloud.android.lib.resources.files.webdav.NCHidden +import com.owncloud.android.lib.resources.files.webdav.NCLock +import com.owncloud.android.lib.resources.files.webdav.NCLockOwner +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerDisplayName +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerEditor +import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerType +import com.owncloud.android.lib.resources.files.webdav.NCLockTime +import com.owncloud.android.lib.resources.files.webdav.NCLockTimeout +import com.owncloud.android.lib.resources.files.webdav.NCLockToken +import com.owncloud.android.lib.resources.files.webdav.NCMetadataGPS +import com.owncloud.android.lib.resources.files.webdav.NCMetadataLivePhoto +import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosGPS +import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosSize +import com.owncloud.android.lib.resources.files.webdav.NCMetadataSize +import com.owncloud.android.lib.resources.files.webdav.NCMountType +import com.owncloud.android.lib.resources.files.webdav.NCNote +import com.owncloud.android.lib.resources.files.webdav.NCPermissions +import com.owncloud.android.lib.resources.files.webdav.NCPreview +import com.owncloud.android.lib.resources.files.webdav.NCRichWorkspace +import com.owncloud.android.lib.resources.files.webdav.NCSharees +import com.owncloud.android.lib.resources.files.webdav.NCTags +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinDeletionTime +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinFilename +import com.owncloud.android.lib.resources.files.webdav.NCTrashbinLocation +import com.owncloud.android.lib.resources.files.webdav.NCUploadTime +import com.owncloud.android.lib.resources.files.webdav.OCCommentsUnread +import com.owncloud.android.lib.resources.files.webdav.OCDisplayName +import com.owncloud.android.lib.resources.files.webdav.OCId +import com.owncloud.android.lib.resources.files.webdav.OCLocalId +import com.owncloud.android.lib.resources.files.webdav.OCOwnerDisplayName +import com.owncloud.android.lib.resources.files.webdav.OCOwnerId +import com.owncloud.android.lib.resources.files.webdav.OCSize +import org.apache.jackrabbit.webdav.MultiStatus +import java.net.URLDecoder + +/** + * WebDav helper. + */ +object WebDavFileUtils2 { + /** + * Read the data retrieved from the server about the contents of the target folder + * + * @param remoteData Full response got from the server with the data of the target + * folder and its direct children. + * @param filesDavUri uri to files webdav uri + * @return content of the target folder + */ + fun readData( + remoteData: MultiStatus, + filesDavUri: Uri, + isReadFolderOperation: Boolean, + isSearchOperation: Boolean + ): ArrayList { + val mFolderAndFiles = ArrayList() + var we: WebdavEntry + var start = 1 + if (isReadFolderOperation) { + we = + WebdavEntry( + remoteData.responses[0], + filesDavUri.encodedPath!! + ) + mFolderAndFiles.add(RemoteFile(we)) + } else { + start = 0 + } + + // loop to update every child + var remoteFile: RemoteFile + val responses = remoteData.responses + for (i in start until responses.size) { + // / new OCFile instance with the data from the server + we = WebdavEntry(responses[i], filesDavUri.encodedPath!!) + remoteFile = RemoteFile(we) + mFolderAndFiles.add(remoteFile) + } + return mFolderAndFiles + } + + fun readData( + responses: List, + filesDavUri: Uri + ): ArrayList { + val list = ArrayList() + for (response in responses) { + list.add(parseResponse(response, filesDavUri)) + } + return list + } + + fun parseResponse( + response: Response, + filesDavUri: Uri + ): RemoteFile { + val remoteFile = RemoteFile() + + val path = "/" + URLDecoder.decode(response.href.toString().substringAfter(filesDavUri.toString()), "UTF-8") + + for (property in response.properties) { + when (property) { + is DisplayName -> remoteFile.name = property.displayName ?: "" + is GetContentLength -> remoteFile.length = property.contentLength + is GetContentType -> remoteFile.mimeType = (property.type ?: "").toString() + is ResourceType -> + if (property.types.contains(ResourceType.COLLECTION)) { + remoteFile.mimeType = WebdavEntry.DIR_TYPE + } + + is NCCreationTime -> remoteFile.creationTimestamp = property.creationTime + is NCEncrypted -> remoteFile.isEncrypted = property.encrypted + is NCEtag -> remoteFile.etag = property.etag + is NCFavorite -> remoteFile.isFavorite = property.favorite + is NCGetLastModified -> remoteFile.modifiedTimestamp = property.lastModified + is NCHidden -> remoteFile.hidden = property.hidden + is NCLock -> remoteFile.isLocked = property.locked + is NCLockOwner -> remoteFile.lockOwner = property.lockOwner + is NCLockOwnerDisplayName -> remoteFile.lockOwnerDisplayName = property.lockOwnerDisplayName + is NCLockOwnerEditor -> remoteFile.lockOwnerEditor = property.lockOwnerEditor + is NCLockOwnerType -> remoteFile.lockType = property.lockOwnerType + is NCLockTime -> remoteFile.lockTimestamp = property.lockTime + is NCLockTimeout -> remoteFile.lockTimeout = property.lockTimeout + is NCLockToken -> remoteFile.lockToken = property.lockToken + is NCMetadataGPS -> remoteFile.geoLocation = property.geoLocation + is NCMetadataLivePhoto -> remoteFile.livePhoto = property.livePhoto + is NCMetadataPhotosGPS -> remoteFile.geoLocation = property.geoLocation + is NCMetadataPhotosSize -> remoteFile.imageDimension = property.imageDimension + is NCMetadataSize -> remoteFile.imageDimension = property.imageDimension + is NCMountType -> remoteFile.mountType = property.mountType + is NCNote -> remoteFile.note = property.note + is NCPermissions -> remoteFile.permissions = property.permissions + is NCPreview -> remoteFile.isHasPreview = property.preview + is NCRichWorkspace -> remoteFile.richWorkspace = property.richWorkspace + is NCSharees -> remoteFile.sharees = property.sharees + is NCTags -> remoteFile.tags = property.tags + is NCTrashbinDeletionTime -> { /* TODO */ } + is NCTrashbinFilename -> { /* TODO */ } + is NCTrashbinLocation -> { /* TODO */ } + is NCUploadTime -> remoteFile.uploadTimestamp = property.uploadTime + is OCCommentsUnread -> remoteFile.unreadCommentsCount = property.commentsCount + is OCDisplayName -> remoteFile.name = property.displayName + is OCId -> remoteFile.remoteId = property.id + is OCLocalId -> remoteFile.localId = property.localId + is OCOwnerDisplayName -> remoteFile.ownerDisplayName = property.ownerDisplayName ?: "" + is OCOwnerId -> remoteFile.ownerId = property.ownerId ?: "" + is OCSize -> remoteFile.size = property.size + } + } + + remoteFile.remotePath = path + + // displayName not set - get from path + if (remoteFile.name?.isEmpty() == true) { + remoteFile.name = path.substringAfterLast("/") + } + + return remoteFile + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt index 52a97a839..70c04f59a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt @@ -4,103 +4,121 @@ * SPDX-FileCopyrightText: 2015 ownCloud Inc. * SPDX-License-Identifier: MIT */ -package com.owncloud.android.lib.resources.files; - -import com.nextcloud.common.SessionTimeOut; -import com.nextcloud.common.SessionTimeOutKt; -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.network.WebdavEntry; -import com.owncloud.android.lib.common.network.WebdavUtils; -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.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 java.util.ArrayList; - +package com.owncloud.android.lib.resources.files + +import androidx.core.net.toUri +import at.bitfire.dav4jvm.DavCollection +import com.nextcloud.common.NextcloudClient +import com.nextcloud.common.SessionTimeOut +import com.nextcloud.common.defaultSessionTimeOut +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.network.WebdavEntry +import com.owncloud.android.lib.common.network.WebdavUtils +import com.owncloud.android.lib.common.network.WebdavUtils2 +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.common.utils.WebDavFileUtils2 +import com.owncloud.android.lib.resources.files.model.RemoteFile +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.apache.commons.httpclient.HttpStatus +import org.apache.jackrabbit.webdav.DavConstants +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod /** * Remote operation performing the read a file from the ownCloud server. - * + * * @author David A. Velasco * @author masensio */ - -public class ReadFileRemoteOperation extends RemoteOperation { - - private static final String TAG = ReadFileRemoteOperation.class.getSimpleName(); - private final String mRemotePath; - private final SessionTimeOut sessionTimeOut; - - - /** - * Constructor - * - * @param remotePath Remote path of the file. - */ - public ReadFileRemoteOperation(String remotePath) { - this(remotePath, SessionTimeOutKt.getDefaultSessionTimeOut()); - } - - public ReadFileRemoteOperation(String remotePath, SessionTimeOut sessionTimeOut) { - mRemotePath = remotePath; - this.sessionTimeOut = sessionTimeOut; - } - +class ReadFileRemoteOperation +/** + * Constructor + * + * @param remotePath Remote path of the file. + */ @JvmOverloads constructor( + private val mRemotePath: String?, + private val sessionTimeOut: SessionTimeOut = defaultSessionTimeOut +) : RemoteOperation() { /** * Performs the read operation. - * + * * @param client Client object to communicate with the remote ownCloud server. */ - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - PropFindMethod propfind = null; - RemoteOperationResult result = null; + override fun run(client: OwnCloudClient): RemoteOperationResult { + var propfind: PropFindMethod? = null + var result: RemoteOperationResult - /// take the duty of check the server for the current state of the file there + /** take the duty of check the server for the current state of the file there */ try { // remote request - propfind = new PropFindMethod(client.getFilesDavUri(mRemotePath), - WebdavUtils.getFilePropSet(), // PropFind Properties - DavConstants.DEPTH_0); - int status; - status = client.executeMethod(propfind, sessionTimeOut.getReadTimeOut(), sessionTimeOut.getConnectionTimeOut()); - - boolean isSuccess = ( - status == HttpStatus.SC_MULTI_STATUS || - status == HttpStatus.SC_OK - ); + propfind = PropFindMethod( + client.getFilesDavUri(mRemotePath), + WebdavUtils.getFilePropSet(), // PropFind Properties + DavConstants.DEPTH_0 + ) + val status: Int + status = client.executeMethod( + propfind, + sessionTimeOut.readTimeOut, + sessionTimeOut.connectionTimeOut + ) + + val isSuccess = (status == HttpStatus.SC_MULTI_STATUS || + status == HttpStatus.SC_OK + ) if (isSuccess) { // Parse response - MultiStatus resp = propfind.getResponseBodyAsMultiStatus(); - WebdavEntry we = new WebdavEntry(resp.getResponses()[0], - client.getFilesDavUri().getEncodedPath()); - RemoteFile remoteFile = new RemoteFile(we); - ArrayList files = new ArrayList(); - files.add(remoteFile); - + val resp = propfind.getResponseBodyAsMultiStatus() + val we = WebdavEntry( + resp.getResponses()[0], + client.getFilesDavUri().getEncodedPath()!! + ) // Result of the operation - result = new RemoteOperationResult<>(true, propfind); - result.setData(files); - + result = RemoteOperationResult(true, propfind) + result.resultData = RemoteFile(we) } else { - result = new RemoteOperationResult<>(false, propfind); - client.exhaustResponse(propfind.getResponseBodyAsStream()); + result = RemoteOperationResult(false, propfind) + client.exhaustResponse(propfind.getResponseBodyAsStream()) } - - } catch (Exception e) { - result = new RemoteOperationResult<>(e); - Log_OC.e(TAG, "Read file " + mRemotePath + " failed: " + result.getLogMessage(), - result.getException()); + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, "Read file " + mRemotePath + " failed: " + result.getLogMessage(), + result.getException() + ) } finally { - if (propfind != null) - propfind.releaseConnection(); + if (propfind != null) { + propfind.releaseConnection() + } + } + return result + } + + override fun run(client: NextcloudClient): RemoteOperationResult { + var result: RemoteFile? = null + val location = client.getFilesDavUri(mRemotePath!!).toHttpUrl() + + val davCollection = DavCollection(client.disabledRedirectClient(), location) + + davCollection.propfind(depth = 1, *WebdavUtils2.PROPERTYSETS.ALL) { response, relation -> + // This callback will be called for every file in the folder. + // Use `response.properties` to access the successfully retrieved properties. + if (response.isSuccess()) { + result = WebDavFileUtils2.parseResponse(response, client.getFilesDavUri("/").toUri()) + } + } + + return if (result == null) { + RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) + } else { + RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { + resultData = result + } } - return result; + } + + companion object { + private val TAG: String = ReadFileRemoteOperation::class.java.getSimpleName() } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index 4c9c56761..c16423dce 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -22,9 +22,7 @@ import java.io.Serializable * * @author masensio */ -class RemoteFile : - Parcelable, - Serializable { +class RemoteFile() : Parcelable, Serializable { var remotePath: String? = null var mimeType: String? = null var length: Long = 0 @@ -44,6 +42,7 @@ class RemoteFile : var unreadCommentsCount = 0 var isHasPreview = false var note: String? = null + var name: String? = null var sharees: Array? = null var richWorkspace: String? = null var isLocked = false @@ -54,16 +53,14 @@ class RemoteFile : var lockOwnerEditor: String? = null var lockTimeout: Long = 0 var lockToken: String? = null - var tags: Array? = null + var tags: Array = emptyArray() var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false var livePhoto: String? = null var fileDownloadLimit: List = emptyList() - constructor() { - resetData() - } + /** * Create new [RemoteFile] with given path. @@ -73,8 +70,7 @@ class RemoteFile : * * @param path The remote path of the file. */ - constructor(path: String?) { - resetData() + constructor(path: String?) : this() { require(!(path.isNullOrEmpty() || !path.startsWith(FileUtils.PATH_SEPARATOR))) { "Trying to create a OCFile with a non valid remote path: $path" } @@ -145,7 +141,7 @@ class RemoteFile : lockTimestamp = 0 lockTimeout = 0 lockToken = null - tags = null + tags = emptyArray() hidden = false livePhoto = null fileDownloadLimit = emptyList() @@ -156,7 +152,7 @@ class RemoteFile : * * @param source The source parcel */ - private constructor(source: Parcel) { + private constructor(source: Parcel) : this() { readFromParcel(source) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt new file mode 100644 index 000000000..e70b22ab5 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt @@ -0,0 +1,28 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser + +class NCCreationTime private constructor(val creationTime: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + return NCCreationTime(parser.text.toLong()) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.CREATION_TIME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt new file mode 100644 index 000000000..8a0d6e02d --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCEncrypted private constructor(val encrypted: Boolean) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCEncrypted("1" == text) + } + } catch (e: IOException) { + Log.e("NCEncrypted", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCEncrypted", "failed to create property", e) + } + return NCEncrypted(false) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.IS_ENCRYPTED.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt new file mode 100644 index 000000000..53bed44d3 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt @@ -0,0 +1,33 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.NS_WEBDAV +import com.owncloud.android.lib.common.network.WebdavUtils +import org.xmlpull.v1.XmlPullParser + +class NCEtag private constructor(val etag: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCEtag { + // + parser.text?.let { rawEtag -> + return NCEtag(WebdavUtils.parseEtag(rawEtag)) + } + return NCEtag(null) + } + } + + companion object { + @JvmField + val NAME = Property.Name(NS_WEBDAV, "getetag") + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt new file mode 100644 index 000000000..73af004c0 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCFavorite private constructor(val favorite: Boolean) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCFavorite("1" == text) + } + } catch (e: IOException) { + Log.e("OCFavorite", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCFavorite", "failed to create property", e) + } + return NCFavorite(false) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.FAVORITE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt new file mode 100644 index 000000000..4f54c2c9d --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt @@ -0,0 +1,36 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.NS_WEBDAV +import com.owncloud.android.lib.common.network.WebdavUtils +import org.xmlpull.v1.XmlPullParser + +class NCGetLastModified private constructor(val lastModified: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCGetLastModified { + // + parser.text?.let { rawDate -> + val date = WebdavUtils.parseResponseDate(rawDate) + if (date != null) { + return NCGetLastModified(date.time) + } + } + return NCGetLastModified(0) + } + } + + companion object { + @JvmField + val NAME = Property.Name(NS_WEBDAV, "getlastmodified") + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt new file mode 100644 index 000000000..9cf00d2e6 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCHidden private constructor(val hidden: Boolean) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCHidden("true" == text) + } + } catch (e: IOException) { + Log.e("NCEncrypted", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCEncrypted", "failed to create property", e) + } + return NCHidden(false) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.HIDDEN.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt new file mode 100644 index 000000000..e0f02d17b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLock private constructor(val locked: Boolean) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLock("1" == text) + } + } catch (e: IOException) { + Log.e("NCEncrypted", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCEncrypted", "failed to create property", e) + } + return NCLock(false) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt new file mode 100644 index 000000000..25ce48114 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockOwner private constructor(val lockOwner: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockOwner(text) + } + } catch (e: IOException) { + Log.e("NCLockOwner", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCLockOwner", "failed to create property", e) + } + return NCLockOwner(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_OWNER.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt new file mode 100644 index 000000000..415429998 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockOwnerDisplayName private constructor(val lockOwnerDisplayName: String) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockOwnerDisplayName(text) + } + } catch (e: IOException) { + Log.e("NCOwnerDisplayName", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCOwnerDisplayName", "failed to create property", e) + } + return NCLockOwnerDisplayName("") + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_OWNER_DISPLAY_NAME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt new file mode 100644 index 000000000..e4cb197cf --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt @@ -0,0 +1,42 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockOwnerEditor private constructor(val lockOwnerEditor: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockOwnerEditor(text) + } + } catch (e: IOException) { + Log.e("NCLockOwnerEditor", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCLockOwnerEditor", "failed to create property", e) + } + return NCLockOwnerEditor(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_OWNER_EDITOR.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt new file mode 100644 index 000000000..abe480d81 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt @@ -0,0 +1,42 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.files.model.FileLockType +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockOwnerType private constructor(val lockOwnerType: FileLockType?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockOwnerType(FileLockType.fromValue(text.toInt())) + } + } catch (e: IOException) { + Log.e("NCLockOwnerType", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCLockOwnerType", "failed to create property", e) + } + return NCLockOwnerType(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_OWNER_TYPE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt new file mode 100644 index 000000000..5431dbee9 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt @@ -0,0 +1,31 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser + +class NCLockTime private constructor(val lockTime: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + parser.text?.let { date -> + return NCLockTime(date.toLong()) + } + return NCLockTime(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_TIME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt new file mode 100644 index 000000000..24f124636 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockTimeout private constructor(val lockTimeout: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockTimeout(text.toLong()) + } + } catch (e: IOException) { + Log.e("NCLockTimeout", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCLockTimeout", "failed to create property", e) + } + return NCLockTimeout(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_TIMEOUT.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt new file mode 100644 index 000000000..86ec51eb0 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCLockToken private constructor(val lockToken: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCLockToken(text) + } + } catch (e: IOException) { + Log.e("NCLockToken", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCLockToken", "failed to create property", e) + } + return NCLockToken(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.LOCK_TOKEN.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt new file mode 100644 index 000000000..03ca75886 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt @@ -0,0 +1,44 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.google.gson.Gson +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.files.model.GeoLocation +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCMetadataGPS private constructor(val geoLocation: GeoLocation?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + val geoLocation = Gson().fromJson(text, GeoLocation::class.java) + return NCMetadataGPS(geoLocation) + } + } catch (e: IOException) { + Log.e("NCMetadataGPS", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCMetadataGPS", "failed to create property", e) + } + return NCMetadataGPS(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.METADATA_GPS.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt new file mode 100644 index 000000000..52007252f --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCMetadataLivePhoto private constructor(val livePhoto: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCMetadataLivePhoto(text) + } + } catch (e: IOException) { + Log.e("NCOwnerDisplayName", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCOwnerDisplayName", "failed to create property", e) + } + return NCMetadataLivePhoto(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.METADATA_LIVE_PHOTO.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt new file mode 100644 index 000000000..7b93c94a0 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt @@ -0,0 +1,61 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.propertyName +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.files.model.GeoLocation +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCMetadataPhotosGPS private constructor(val geoLocation: GeoLocation) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + return NCMetadataPhotosGPS(parseText(parser)) + } + + @Suppress("NestedBlockDepth") + private fun parseText(parser: XmlPullParser): GeoLocation { + var latitude = 0.0 + var longitude = 0.0 + + val depth = parser.depth + var eventType = parser.eventType + + try { + while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { + if (eventType != XmlPullParser.TEXT) { + when (parser.propertyName().name) { + "latitude" -> parser.text?.let { latitude = it.toDouble() } + "longitude" -> parser.text?.let { longitude = it.toDouble() } + } + } + + eventType = parser.next() + } + } catch (e: IOException) { + Log.e("NCMetadataPhotosGPS", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCMetadataPhotosGPS", "failed to create property", e) + } + + return GeoLocation(latitude, longitude) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.METADATA_PHOTOS_GPS.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt new file mode 100644 index 000000000..a52a842af --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt @@ -0,0 +1,61 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.propertyName +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.files.model.ImageDimension +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCMetadataPhotosSize private constructor(val imageDimension: ImageDimension) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + return NCMetadataPhotosSize(parseText(parser)) + } + + @Suppress("NestedBlockDepth") + private fun parseText(parser: XmlPullParser): ImageDimension { + var width = 0.0f + var height = 0.0f + + val depth = parser.depth + var eventType = parser.eventType + + try { + while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { + if (eventType != XmlPullParser.TEXT) { + when (parser.propertyName().name) { + "width" -> parser.text?.let { width = it.toFloat() } + "height" -> parser.text?.let { height = it.toFloat() } + } + } + + eventType = parser.next() + } + } catch (e: IOException) { + Log.e("NCMetadataPhotosSize", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCMetadataPhotosSize", "failed to create property", e) + } + + return ImageDimension(width, height) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.METADATA_PHOTOS_SIZE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt new file mode 100644 index 000000000..510392202 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt @@ -0,0 +1,44 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.google.gson.Gson +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.files.model.ImageDimension +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCMetadataSize private constructor(val imageDimension: ImageDimension?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + val imageDimension = Gson().fromJson(text, ImageDimension::class.java) + return NCMetadataSize(imageDimension) + } + } catch (e: IOException) { + Log.e("NCMetadataSize", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCMetadataSize", "failed to create property", e) + } + return NCMetadataSize(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.METADATA_SIZE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt new file mode 100644 index 000000000..0eb7bca11 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt @@ -0,0 +1,37 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.common.network.WebdavEntry +import org.xmlpull.v1.XmlPullParser + +class NCMountType private constructor(val mountType: WebdavEntry.MountType) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCMountType { + // (#PCDATA) > + val type = parser.text + return NCMountType( + when (type) { + "external" -> WebdavEntry.MountType.EXTERNAL + "group" -> WebdavEntry.MountType.GROUP + else -> WebdavEntry.MountType.INTERNAL + } + ) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.MOUNT_TYPE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt new file mode 100644 index 000000000..d6fb2a2da --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCNote private constructor(val note: String) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCNote(text) + } + } catch (e: IOException) { + Log.e("NCNote", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCNote", "failed to create property", e) + } + return NCNote("") + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.NOTE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt new file mode 100644 index 000000000..555ad2c23 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCPermissions private constructor(val permissions: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCPermissions(text) + } + } catch (e: IOException) { + Log.e("NCPermissions", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCPermissions", "failed to create property", e) + } + return NCPermissions(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.NAME_PERMISSIONS.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt new file mode 100644 index 000000000..66aefcdde --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCPreview private constructor(val preview: Boolean) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCPreview(text.toBoolean()) + } + } catch (e: IOException) { + Log.e("NCPreview", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCPreview", "failed to create property", e) + } + return NCPreview(false) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.HAS_PREVIEW.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt new file mode 100644 index 000000000..8f42df821 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCRichWorkspace private constructor(val richWorkspace: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCRichWorkspace { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCRichWorkspace(text) + } + } catch (e: IOException) { + Log.e("NCRichWorkspace", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCRichWorkspace", "failed to create property", e) + } + return NCRichWorkspace(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.RICH_WORKSPACE.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt new file mode 100644 index 000000000..05109fd07 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt @@ -0,0 +1,118 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import androidx.annotation.VisibleForTesting +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.propertyName +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.lib.resources.shares.ShareeUser +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCSharees private constructor(val sharees: Array) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCSharees { + // NC sharees property + readArrayNode(parser).let { sharees -> + return NCSharees(sharees.toTypedArray()) + } + } + + @Throws(IOException::class, XmlPullParserException::class) + @VisibleForTesting + fun readArrayNode(parser: XmlPullParser): List { + var list: List = emptyList() + + val depth = parser.depth + var eventType = parser.eventType + while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { + if (eventType != XmlPullParser.TEXT) { + list = readNCSharees(parser) + } + if (parser.eventType == XmlPullParser.END_TAG && parser.depth == depth) { + return list + } + + eventType = parser.next() + } + + return list + } + + private fun readNCSharees(parser: XmlPullParser): List { + val list: ArrayList = ArrayList() + + val depth = parser.depth + var eventType = parser.eventType + while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + // only add non-null users + readNCSharee(parser)?.let { list.add(it) } + } + + eventType = parser.next() + } + + return list + } + + private fun readNCSharee(parser: XmlPullParser): ShareeUser? { + val depth = parser.depth + var eventType = parser.eventType + + var userId: String? = null + var displayName: String? = null + var shareType: ShareType? = null + + while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { + if (eventType != XmlPullParser.TEXT) { + when (parser.propertyName()) { + ExtendedProperties.SHAREES_ID.toPropertyName() -> { + userId = parser.text + } + + ExtendedProperties.SHAREES_DISPLAY_NAME.toPropertyName() -> { + displayName = parser.text + } + + ExtendedProperties.SHAREES_SHARE_TYPE.toPropertyName() -> { + shareType = ShareType.fromValue(parser.text?.toInt() ?: 0) + } + } + } + + eventType = parser.next() + } + + // check that user is an actual sharee - e.g. exclude link shares + + val isSupportedShareType = + ShareType.EMAIL == shareType || + ShareType.FEDERATED == shareType || + ShareType.GROUP == shareType || + ShareType.ROOM == shareType + + return if (userId.isNullOrEmpty() || (displayName.isNullOrEmpty() && !isSupportedShareType)) { + null + } else { + ShareeUser(userId, displayName, shareType) + } + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.SHAREES.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt new file mode 100644 index 000000000..a412c8bf5 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt @@ -0,0 +1,104 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import androidx.annotation.VisibleForTesting +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.propertyName +import com.owncloud.android.lib.common.network.ExtendedProperties +import com.owncloud.android.lib.resources.tags.Tag +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCTags private constructor(val tags: Array) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCTags { + // NC tags property + readArrayNode(parser).let { tags -> + return NCTags(tags.toTypedArray()) + } + } + + @Throws(IOException::class, XmlPullParserException::class) + @VisibleForTesting + fun readArrayNode(parser: XmlPullParser): List { + var list: List = emptyList() + + val depth = parser.depth + var eventType = parser.eventType + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType != XmlPullParser.TEXT) { + list = readNCTags(parser) + } + if (parser.eventType == XmlPullParser.END_TAG && parser.depth == depth) { + return list + } + + eventType = parser.next() + } + + return list + } + + private fun readNCTags(parser: XmlPullParser): List { + val list: ArrayList = ArrayList() + + val depth = parser.depth + var eventType = parser.eventType + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + list.add(readNCTag(parser)) + } + + eventType = parser.next() + } + + return list + } + + private fun readNCTag(parser: XmlPullParser): Tag { + val depth = parser.depth + var eventType = parser.eventType + + var id = "" + var name = "" + var color = "" + + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType != XmlPullParser.TEXT) { + when (parser.propertyName().toString()) { + "http://nextcloud.org/ns:id" -> { + id = parser.text + } + + "http://nextcloud.org/ns:name" -> { + name = parser.text + } + + "http://nextcloud.org/ns:color" -> { + color = parser.text + } + } + } + + eventType = parser.next() + } + + return Tag(id, name, color) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.SYSTEM_TAGS.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt new file mode 100644 index 000000000..489449ded --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCTrashbinDeletionTime private constructor(val deletionTime: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCTrashbinDeletionTime(text.toLong()) + } + } catch (e: IOException) { + Log.e("NCTrashbinDeletionTime", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCTrashbinDeletionTime", "failed to create property", e) + } + return NCTrashbinDeletionTime(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.TRASHBIN_DELETION_TIME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt new file mode 100644 index 000000000..782b5b96b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCTrashbinFilename private constructor(val originalLocation: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCTrashbinFilename(text) + } + } catch (e: IOException) { + Log.e("NCTrashbinFilename", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCTrashbinFilename", "failed to create property", e) + } + return NCTrashbinFilename(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.TRASHBIN_FILENAME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt new file mode 100644 index 000000000..3ac92fb20 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCTrashbinLocation private constructor(val originalLocation: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCTrashbinLocation(text) + } + } catch (e: IOException) { + Log.e("NCTrashbinLocation", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCTrashbinLocation", "failed to create property", e) + } + return NCTrashbinLocation(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.TRASHBIN_ORIGINAL_LOCATION.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt new file mode 100644 index 000000000..e7ea1bff8 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCUploadTime private constructor(val uploadTime: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return NCUploadTime(text.toLong()) + } + } catch (e: IOException) { + Log.e("NCUploadTime", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("NCUploadTime", "failed to create property", e) + } + return NCUploadTime(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.UPLOAD_TIME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt new file mode 100644 index 000000000..bebc9feba --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCCommentsUnread private constructor(val commentsCount: Int) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCCommentsUnread(text.toInt()) + } + } catch (e: IOException) { + Log.e("OCCommentsUnread", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCCommentsUnread", "failed to create property", e) + } + return OCCommentsUnread(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.UNREAD_COMMENTS.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt new file mode 100644 index 000000000..4d1afe7d8 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCDisplayName private constructor(val displayName: String) : Property { + class Factory : PropertyFactory { + override fun getName(): Property.Name = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCDisplayName(text) + } + } catch (e: IOException) { + Log.e("OCDisplayName", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCDisplayName", "failed to create property", e) + } + return OCDisplayName("") + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.DISPLAY_NAME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt new file mode 100644 index 000000000..469f4e457 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCId private constructor(val id: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCId(text) + } + } catch (e: IOException) { + Log.e("OCId", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCId", "failed to create property", e) + } + return OCId(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.NAME_REMOTE_ID.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt new file mode 100644 index 000000000..65f35046b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCLocalId private constructor(val localId: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCLocalId(text.toLong()) + } + } catch (e: IOException) { + Log.e("OCLocalId", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCLocalId", "failed to create property", e) + } + return OCLocalId(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.NAME_LOCAL_ID.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt new file mode 100644 index 000000000..1e724a2b5 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCOwnerDisplayName private constructor(val ownerDisplayName: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCOwnerDisplayName(text) + } + } catch (e: IOException) { + Log.e("OCOwnerDisplayName", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCOwnerDisplayName", "failed to create property", e) + } + return OCOwnerDisplayName(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.OWNER_DISPLAY_NAME.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt new file mode 100644 index 000000000..f01223a53 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCOwnerId private constructor(val ownerId: String?) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCOwnerId(text) + } + } catch (e: IOException) { + Log.e("OCOwnerId", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCOwnerId", "failed to create property", e) + } + return OCOwnerId(null) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.OWNER_ID.toPropertyName() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt new file mode 100644 index 000000000..f73c90d16 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.util.Log +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import com.owncloud.android.lib.common.network.ExtendedProperties +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCSize private constructor(val size: Long) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Property { + try { + val text = parser.text + if (!text.isNullOrEmpty()) { + return OCSize(text.toLong()) + } + } catch (e: IOException) { + Log.e("OCSize", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCSize", "failed to create property", e) + } + return OCSize(0) + } + } + + companion object { + @JvmField + val NAME = ExtendedProperties.NAME_SIZE.toPropertyName() + } +} diff --git a/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt b/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt index 1de00c2e6..3acb691cc 100644 --- a/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt +++ b/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt @@ -55,7 +55,7 @@ class NextcloudClientTest { val exception = RuntimeException("test exception") val operation = object : RemoteOperation() { - override fun run(client: NextcloudClient?): RemoteOperationResult = throw exception + override suspend fun run(client: NextcloudClient?): RemoteOperationResult = throw exception } // WHEN From dd007f1b2994f97fb581fa1460521f5c5213556e Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 25 Aug 2026 12:10:07 +0200 Subject: [PATCH 3/6] wip Signed-off-by: tobiasKaminsky --- ...irectEditingOpenFileRemoteOperationIT.java | 14 +- .../files/ToggleFileLockRemoteOperationIT.kt | 7 +- .../java/com/owncloud/android/AbstractIT.java | 6 +- .../CreateFolderRemoteOperationIT.java | 4 +- .../comments/CommentFileRemoteOperationIT.kt | 5 +- .../e2ee/UpdateMetadataRemoteOperationIT.kt | 7 +- .../files/CheckEtagRemoteOperationIT.kt | 4 +- .../files/ReadFileRemoteOperationIT.kt | 75 ++++- .../ReadFileVersionsRemoteOperationIT.kt | 5 +- .../files/SearchRemoteOperationIT.java | 2 +- .../files/UploadFileRemoteOperationIT.kt | 4 +- .../tags/DeleteTagRemoteOperationIT.kt | 4 +- .../tags/GetTagsRemoteOperationIT.kt | 6 +- .../common/NextcloudAuthenticator.kt | 7 +- .../com/nextcloud/common/NextcloudClient.kt | 17 +- .../common/WebDavUtils.kt} | 263 +++++++++++++----- .../nextcloud/operations/PropFindMethod2.kt | 5 +- .../nextcloud/operations/PropFindResult.kt | 4 +- .../owncloud/android/lib/common/DavMethod.kt | 29 -- .../lib/common/network/ExtendedProperties.kt | 12 +- .../lib/common/utils/WebDavFileUtils2.kt | 180 ------------ .../files/ReadFileRemoteOperation.kt | 153 +++++----- .../lib/resources/files/model/RemoteFile.kt | 8 +- .../resources/files/webdav/NCCreationTime.kt | 12 +- .../lib/resources/files/webdav/NCEncrypted.kt | 9 +- .../lib/resources/files/webdav/NCEtag.kt | 9 +- .../lib/resources/files/webdav/NCFavorite.kt | 9 +- .../files/webdav/NCGetLastModified.kt | 9 +- .../lib/resources/files/webdav/NCHidden.kt | 9 +- .../lib/resources/files/webdav/NCLock.kt | 9 +- .../lib/resources/files/webdav/NCLockOwner.kt | 9 +- .../files/webdav/NCLockOwnerDisplayName.kt | 9 +- .../files/webdav/NCLockOwnerEditor.kt | 7 +- .../resources/files/webdav/NCLockOwnerType.kt | 9 +- .../lib/resources/files/webdav/NCLockTime.kt | 9 +- .../resources/files/webdav/NCLockTimeout.kt | 9 +- .../lib/resources/files/webdav/NCLockToken.kt | 9 +- .../resources/files/webdav/NCMetadataGPS.kt | 9 +- .../files/webdav/NCMetadataLivePhoto.kt | 9 +- .../files/webdav/NCMetadataPhotosGPS.kt | 15 +- .../files/webdav/NCMetadataPhotosSize.kt | 15 +- .../resources/files/webdav/NCMetadataSize.kt | 9 +- .../lib/resources/files/webdav/NCMountType.kt | 9 +- .../lib/resources/files/webdav/NCNote.kt | 9 +- .../resources/files/webdav/NCPermissions.kt | 9 +- .../lib/resources/files/webdav/NCPreview.kt | 9 +- .../resources/files/webdav/NCRichWorkspace.kt | 9 +- .../lib/resources/files/webdav/NCSharees.kt | 13 +- .../lib/resources/files/webdav/NCTags.kt | 15 +- .../files/webdav/NCTrashbinDeletionTime.kt | 9 +- .../files/webdav/NCTrashbinFilename.kt | 9 +- .../files/webdav/NCTrashbinLocation.kt | 9 +- .../resources/files/webdav/NCUploadTime.kt | 9 +- .../files/webdav/OCCommentsUnread.kt | 9 +- .../resources/files/webdav/OCDisplayName.kt | 9 +- .../lib/resources/files/webdav/OCId.kt | 9 +- .../lib/resources/files/webdav/OCLocalId.kt | 9 +- .../files/webdav/OCOwnerDisplayName.kt | 9 +- .../lib/resources/files/webdav/OCOwnerId.kt | 9 +- .../lib/resources/files/webdav/OCSize.kt | 9 +- 60 files changed, 628 insertions(+), 549 deletions(-) rename library/src/main/java/com/{owncloud/android/lib/common/network/WebdavUtils2.kt => nextcloud/common/WebDavUtils.kt} (58%) delete mode 100644 library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt delete mode 100644 library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt diff --git a/library/src/androidTest/java/com/nextcloud/android/lib/resources/directediting/DirectEditingOpenFileRemoteOperationIT.java b/library/src/androidTest/java/com/nextcloud/android/lib/resources/directediting/DirectEditingOpenFileRemoteOperationIT.java index 9f23bf3a7..f4680c072 100644 --- a/library/src/androidTest/java/com/nextcloud/android/lib/resources/directediting/DirectEditingOpenFileRemoteOperationIT.java +++ b/library/src/androidTest/java/com/nextcloud/android/lib/resources/directediting/DirectEditingOpenFileRemoteOperationIT.java @@ -7,6 +7,9 @@ */ package com.nextcloud.android.lib.resources.directediting; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import com.owncloud.android.AbstractIT; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; @@ -18,9 +21,6 @@ import java.io.IOException; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - public class DirectEditingOpenFileRemoteOperationIT extends AbstractIT { @Test public void openFile() throws IOException { @@ -34,7 +34,7 @@ public void openFile() throws IOException { 1464818400 ).execute(client).isSuccess()); - TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(client).isSuccess()); + TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(nextcloudClient).isSuccess()); // open file RemoteOperationResult result = new DirectEditingOpenFileRemoteOperation(remotePath, "text") @@ -58,7 +58,7 @@ public void openFileWithSpecialChars() throws IOException { 1464818400 ).execute(client).isSuccess()); - TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(client).isSuccess()); + TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(nextcloudClient).isSuccess()); // open file RemoteOperationResult result = new DirectEditingOpenFileRemoteOperation(remotePath, "text") @@ -82,7 +82,7 @@ public void openFileWithSpecialChars2() throws IOException { 1464818400 ).execute(client).isSuccess()); - TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(client).isSuccess()); + TestCase.assertTrue(new ReadFileRemoteOperation(remotePath).execute(nextcloudClient).isSuccess()); // open file RemoteOperationResult result = new DirectEditingOpenFileRemoteOperation(remotePath, "text") @@ -98,7 +98,7 @@ public void openFileWithSpecialChars2() throws IOException { public void openNonExistingFile() { String remotePath = "/nonExisting.md"; - TestCase.assertFalse(new ReadFileRemoteOperation(remotePath).execute(client).isSuccess()); + TestCase.assertFalse(new ReadFileRemoteOperation(remotePath).execute(nextcloudClient).isSuccess()); // open file RemoteOperationResult result = new DirectEditingOpenFileRemoteOperation(remotePath, "text") diff --git a/library/src/androidTest/java/com/nextcloud/android/lib/resources/files/ToggleFileLockRemoteOperationIT.kt b/library/src/androidTest/java/com/nextcloud/android/lib/resources/files/ToggleFileLockRemoteOperationIT.kt index ec029da67..0898f1ee3 100644 --- a/library/src/androidTest/java/com/nextcloud/android/lib/resources/files/ToggleFileLockRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/nextcloud/android/lib/resources/files/ToggleFileLockRemoteOperationIT.kt @@ -11,7 +11,6 @@ import com.owncloud.android.AbstractIT import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation import com.owncloud.android.lib.resources.files.model.FileLockType -import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.status.NextcloudVersion.Companion.nextcloud_24 import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -34,20 +33,20 @@ class ToggleFileLockRemoteOperationIT : AbstractIT() { .isSuccess ) val initialFile = - ReadFileRemoteOperation(remotePath).execute(client).singleData as RemoteFile + ReadFileRemoteOperation(remotePath).execute(nextcloudClient).resultData assertFalse("File shouldn't be locked", initialFile.isLocked) // lock file val lockResult = ToggleFileLockRemoteOperation(toLock = true, remotePath).execute(nextcloudClient) assertTrue("File lock failed", lockResult.isSuccess) - val lockFile = ReadFileRemoteOperation(remotePath).execute(client).singleData as RemoteFile + val lockFile = ReadFileRemoteOperation(remotePath).execute(nextcloudClient).resultData assertTrue("File should be locked", lockFile.isLocked) assertEquals("Wrong lock type", FileLockType.MANUAL, lockFile.lockType) // unlock again val unlockResult = ToggleFileLockRemoteOperation(toLock = false, remotePath).execute(nextcloudClient) assertTrue("File unlock failed", unlockResult.isSuccess) - val unlockFile = ReadFileRemoteOperation(remotePath).execute(client).singleData as RemoteFile + val unlockFile = ReadFileRemoteOperation(remotePath).execute(nextcloudClient).resultData assertFalse("File shouldn't be locked", unlockFile.isLocked) } } diff --git a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java index 59a163689..4aa0cb1b1 100644 --- a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -94,6 +94,10 @@ public static void beforeAll() throws InterruptedException, String loginName = arguments.getString("TEST_SERVER_USERNAME"); String password = arguments.getString("TEST_SERVER_PASSWORD"); + // E2E server app checks for official NC client with >=3.13.0, + // and blocks all other clients, e.g. 3rd party apps using this lib + OwnCloudClientManagerFactory.setUserAgent("Mozilla/5.0 (Android) Nextcloud-android/3.13.0"); + client = OwnCloudClientFactory.createOwnCloudClient(url, context, true); client.setCredentials(new OwnCloudBasicCredentials(loginName, password)); client.setUserId(loginName); // for test same as userId @@ -106,8 +110,6 @@ public static void beforeAll() throws InterruptedException, client2.setCredentials(new OwnCloudBasicCredentials(loginName2, password2)); client2.setUserId(loginName2); // for test same as userId - OwnCloudClientManagerFactory.setUserAgent("Mozilla/5.0 (Android) Nextcloud-android/1.0.0"); - String userId = loginName; // for test same as userId String credentials = Credentials.basic(loginName, password); nextcloudClient = new NextcloudClient(url, userId, credentials, context); diff --git a/library/src/androidTest/java/com/owncloud/android/CreateFolderRemoteOperationIT.java b/library/src/androidTest/java/com/owncloud/android/CreateFolderRemoteOperationIT.java index 4f7b02dfc..9740eea68 100644 --- a/library/src/androidTest/java/com/owncloud/android/CreateFolderRemoteOperationIT.java +++ b/library/src/androidTest/java/com/owncloud/android/CreateFolderRemoteOperationIT.java @@ -92,10 +92,10 @@ public void testFileID() { RemoteOperationResult result = new CreateFolderRemoteOperation(remotePath, true).execute(client); assertTrue(result.isSuccess()); - RemoteOperationResult readResult = new ReadFileRemoteOperation(remotePath).execute(client); + RemoteOperationResult readResult = new ReadFileRemoteOperation(remotePath).execute(nextcloudClient); assertTrue(readResult.isSuccess()); - String remoteId = ((RemoteFile) readResult.getData().get(0)).getRemoteId(); + String remoteId = readResult.getResultData().getRemoteId(); assertEquals(result.getResultData(), remoteId); } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/comments/CommentFileRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/comments/CommentFileRemoteOperationIT.kt index f344633eb..947aa39bc 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/comments/CommentFileRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/comments/CommentFileRemoteOperationIT.kt @@ -10,7 +10,6 @@ package com.owncloud.android.lib.resources.comments import com.owncloud.android.AbstractIT 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 junit.framework.Assert.assertTrue import org.junit.Test @@ -25,8 +24,8 @@ class CommentFileRemoteOperationIT : AbstractIT() { .isSuccess ) - val readResult = ReadFileRemoteOperation(remotePath).execute(client) - val remoteFile = readResult.data.get(0) as RemoteFile + val readResult = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) + val remoteFile = readResult.resultData assertTrue( CommentFileRemoteOperation("test", remoteFile.localId) 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..8b0f2271c 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 @@ -14,7 +14,6 @@ import com.owncloud.android.AbstractIT import com.owncloud.android.lib.common.OwnCloudClientManagerFactory import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation -import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.status.OwnCloudVersion import junit.framework.TestCase import org.junit.Assert @@ -33,8 +32,7 @@ class UpdateMetadataRemoteOperationIT : AbstractIT() { // create folder val folder = "/" + make(20) + "/" TestCase.assertTrue(CreateFolderRemoteOperation(folder, true).execute(client).isSuccess) - val remoteFolder = - ReadFileRemoteOperation(folder).execute(client).getSingleData() as RemoteFile? + val remoteFolder = ReadFileRemoteOperation(folder).execute(nextcloudClient).resultData TestCase.assertNotNull(remoteFolder) @@ -117,8 +115,7 @@ class UpdateMetadataRemoteOperationIT : AbstractIT() { // create folder val folder = "/" + make(20) + "/" TestCase.assertTrue(CreateFolderRemoteOperation(folder, true).execute(client).isSuccess) - val remoteFolder = - ReadFileRemoteOperation(folder).execute(client).getSingleData() as RemoteFile? + val remoteFolder = ReadFileRemoteOperation(folder).execute(nextcloudClient).resultData TestCase.assertNotNull(remoteFolder) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/CheckEtagRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/CheckEtagRemoteOperationIT.kt index 44123907c..155fbb8e0 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/CheckEtagRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/CheckEtagRemoteOperationIT.kt @@ -9,7 +9,6 @@ package com.owncloud.android.lib.resources.files import com.owncloud.android.AbstractIT import com.owncloud.android.lib.common.operations.RemoteOperationResult -import com.owncloud.android.lib.resources.files.model.RemoteFile import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -26,8 +25,7 @@ class CheckEtagRemoteOperationIT : AbstractIT() { .isSuccess ) - val readResult = ReadFileRemoteOperation(remotePath).execute(client) - val remoteFile = readResult.data[0] as RemoteFile + val remoteFile = ReadFileRemoteOperation(remotePath).execute(nextcloudClient).resultData val eTag = remoteFile.etag var eTagResult = CheckEtagRemoteOperation(remotePath, eTag).execute(client) 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 3c430d77a..bede2b35a 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 @@ -8,10 +8,10 @@ package com.owncloud.android.lib.resources.files import com.owncloud.android.AbstractIT -import com.owncloud.android.lib.common.OwnCloudClientManagerFactory import com.owncloud.android.lib.resources.e2ee.ToggleEncryptionRemoteOperation 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.status.GetCapabilitiesRemoteOperation import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertEquals @@ -26,13 +26,20 @@ class ReadFileRemoteOperationIT : AbstractIT() { assertTrue(CreateFolderRemoteOperation(remotePath, true).execute(client).isSuccess) + // use ownCloud client for reference var result = ReadFileRemoteOperation(remotePath).execute(client) assertTrue(result.isSuccess) - assertEquals(remotePath, result.resultData.remotePath) - + val ocClientFile = result.resultData + assertEquals(remotePath, ocClientFile.remotePath) + result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) + val ncClientFile = result.resultData assertEquals(remotePath, result.resultData.remotePath) + + assertEquals(ocClientFile.modifiedTimestamp, ncClientFile.modifiedTimestamp) + + assertTrue(remoteFilesEqual(ocClientFile, ncClientFile)) } @Test @@ -70,11 +77,11 @@ class ReadFileRemoteOperationIT : AbstractIT() { ).execute(client).isSuccess ) - val movieFileResult = ReadFileRemoteOperation(movieFilePath).execute(client) + val movieFileResult = ReadFileRemoteOperation(movieFilePath).execute(nextcloudClient) assertTrue(movieFileResult.isSuccess) val movieRemoteFile = movieFileResult.resultData - val livePhotoResult = ReadFileRemoteOperation(livePhotoPath).execute(client) + val livePhotoResult = ReadFileRemoteOperation(livePhotoPath).execute(nextcloudClient) assertTrue(livePhotoResult.isSuccess) val livePhotoRemoteFile = livePhotoResult.resultData @@ -93,13 +100,18 @@ class ReadFileRemoteOperationIT : AbstractIT() { .isSuccess ) + // use ownCloud client for reference var result = ReadFileRemoteOperation(remotePath).execute(client) assertTrue(result.isSuccess) - assertEquals(remotePath, result.resultData.remotePath) + val ocClientFile = result.resultData + assertEquals(remotePath, ocClientFile.remotePath) result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) + val ncClientFile = result.resultData assertEquals(remotePath, result.resultData.remotePath) + + assertTrue(remoteFilesEqual(ocClientFile, ncClientFile)) } @Test @@ -113,7 +125,7 @@ class ReadFileRemoteOperationIT : AbstractIT() { .isSuccess ) - val result = ReadFileRemoteOperation(remotePath).execute(client) + val result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) val remoteFile = result.resultData @@ -139,14 +151,9 @@ class ReadFileRemoteOperationIT : AbstractIT() { @Test fun readEncryptedState() { val remotePath = "/testEncryptedFolder/" - - // E2E server app checks for official NC client with >=3.13.0, - // and blocks all other clients, e.g. 3rd party apps using this lib - OwnCloudClientManagerFactory.setUserAgent("Mozilla/5.0 (Android) Nextcloud-android/3.13.0") - assertTrue(CreateFolderRemoteOperation(remotePath, true).execute(client).isSuccess) - var result = ReadFileRemoteOperation(remotePath).execute(client) + var result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) val remoteFile = result.resultData assertTrue(result.isSuccess) @@ -164,7 +171,47 @@ class ReadFileRemoteOperationIT : AbstractIT() { ) // re-read - result = ReadFileRemoteOperation(remotePath).execute(client) + result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertEquals(true, result.resultData.isEncrypted) } + + private fun remoteFilesEqual( + a: RemoteFile, + b: RemoteFile + ): Boolean = + a.remotePath == b.remotePath && + a.mimeType == b.mimeType && + a.length == b.length && + a.creationTimestamp == b.creationTimestamp && + a.modifiedTimestamp == b.modifiedTimestamp && + a.uploadTimestamp == b.uploadTimestamp && + a.etag == b.etag && + a.permissions == b.permissions && + a.localId == b.localId && + a.remoteId == b.remoteId && + a.size == b.size && + a.isFavorite == b.isFavorite && + a.isEncrypted == b.isEncrypted && + a.mountType == b.mountType && + a.ownerId == b.ownerId && + a.ownerDisplayName == b.ownerDisplayName && + a.unreadCommentsCount == b.unreadCommentsCount && + a.isHasPreview == b.isHasPreview && + a.note == b.note && + a.sharees.contentEquals(b.sharees) && + a.richWorkspace == b.richWorkspace && + a.isLocked == b.isLocked && + a.lockType == b.lockType && + a.lockOwner == b.lockOwner && + a.lockOwnerDisplayName == b.lockOwnerDisplayName && + a.lockTimestamp == b.lockTimestamp && + a.lockOwnerEditor == b.lockOwnerEditor && + a.lockTimeout == b.lockTimeout && + a.lockToken == b.lockToken && + a.tags.contentEquals(b.tags) && + a.imageDimension == b.imageDimension && + a.geoLocation == b.geoLocation && + a.hidden == b.hidden && + a.livePhoto == b.livePhoto && + a.fileDownloadLimit == b.fileDownloadLimit } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileVersionsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileVersionsRemoteOperationIT.kt index 816112e11..2438e658f 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileVersionsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileVersionsRemoteOperationIT.kt @@ -8,7 +8,6 @@ package com.owncloud.android.lib.resources.files import com.owncloud.android.AbstractIT -import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.status.GetCapabilitiesRemoteOperation import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertEquals @@ -33,7 +32,7 @@ class ReadFileVersionsRemoteOperationIT : AbstractIT() { assertTrue("Error uploading file $filePath: $uploadResult", uploadResult.isSuccess) - var remoteFile = ReadFileRemoteOperation(filePath).execute(client).data[0] as RemoteFile + var remoteFile = ReadFileRemoteOperation(filePath).execute(nextcloudClient).resultData var sutResult = ReadFileVersionsRemoteOperation(remoteFile.localId).execute(client) @@ -64,7 +63,7 @@ class ReadFileVersionsRemoteOperationIT : AbstractIT() { assertTrue("Error uploading file $filePath: $uploadResult", uploadResult.isSuccess) - remoteFile = ReadFileRemoteOperation(filePath).execute(client).data[0] as RemoteFile + remoteFile = ReadFileRemoteOperation(filePath).execute(nextcloudClient).resultData sutResult = ReadFileVersionsRemoteOperation(remoteFile.localId).execute(client) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java index dda961ed4..d861468ee 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java @@ -57,7 +57,7 @@ public void testSearchByFileIdEmpty() { public void testSearchByFileIdSuccess() { assertTrue(new CreateFolderRemoteOperation("/test/", true).execute(client).isSuccess()); - RemoteOperationResult readFile = new ReadFileRemoteOperation("/test/").execute(client); + RemoteOperationResult readFile = new ReadFileRemoteOperation("/test/").execute(nextcloudClient); assertTrue(readFile.isSuccess()); RemoteFile remoteFile = ((RemoteFile) readFile.getSingleData()); 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 43f933fa3..24ffc4659 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) + val result = ReadFileRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) - var remoteFile = result.data[0] as RemoteFile + var remoteFile = result.resultData assertEquals(remotePath, remoteFile.remotePath) assertEquals(creationTimestamp, remoteFile.creationTimestamp) 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..452922c22 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 @@ -29,8 +29,8 @@ class DeleteTagRemoteOperationIT : AbstractIT() { // create a folder val folder = "/deleteTagFolder/" assertTrue(CreateFolderRemoteOperation(folder, true).execute(client).isSuccess) - val folderMetadata = ReadFileRemoteOperation(folder).execute(client) - val fileId = (folderMetadata.data[0] as RemoteFile).localId + val folderMetadata = ReadFileRemoteOperation(folder).execute(nextcloudClient) + val fileId = folderMetadata.resultData.localId // create a tag val tagName = RandomStringGenerator.make(TAG_LENGTH) 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..6df323fde 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 @@ -108,17 +108,17 @@ class GetTagsRemoteOperationIT : AbstractIT() { // add colored tag to file val tagFolder = "/coloredFolder/" assertTrue(CreateFolderRemoteOperation(tagFolder, true).execute(client).isSuccess) - val folderMetadata = ReadFileRemoteOperation(tagFolder).execute(client) + val folderMetadata = ReadFileRemoteOperation(tagFolder).execute(nextcloudClient) assertTrue( PutTagRemoteOperation( tag1.id, - (folderMetadata.data[0] as RemoteFile).localId + folderMetadata.resultData.localId ).execute(nextcloudClient).isSuccess ) assertTrue( PutTagRemoteOperation( tag2.id, - (folderMetadata.data[0] as RemoteFile).localId + folderMetadata.resultData.localId ).execute(nextcloudClient).isSuccess ) diff --git a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt index 139fd5e4e..4b751ff73 100644 --- a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt +++ b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt @@ -12,7 +12,9 @@ import okhttp3.Request import okhttp3.Response import okhttp3.Route -class NextcloudAuthenticator(private val credentials: String) : Authenticator { +class NextcloudAuthenticator( + private val credentials: String +) : Authenticator { @Suppress("ReturnCount") override fun authenticate( route: Route?, @@ -39,7 +41,8 @@ class NextcloudAuthenticator(private val credentials: String) : Authenticator { countedResponse = countedResponse.priorResponse } - return response.request.newBuilder() + return response.request + .newBuilder() .header(authenticatorType, credentials) .build() } diff --git a/library/src/main/java/com/nextcloud/common/NextcloudClient.kt b/library/src/main/java/com/nextcloud/common/NextcloudClient.kt index d4f361744..8bf798329 100644 --- a/library/src/main/java/com/nextcloud/common/NextcloudClient.kt +++ b/library/src/main/java/com/nextcloud/common/NextcloudClient.kt @@ -82,6 +82,8 @@ class NextcloudClient private constructor( Log_OC.d(this, "Proxy settings: $proxyHost:$proxyPort") } + val userAgent = OwnCloudClientManagerFactory.getUserAgent() + return OkHttpClient .Builder() .cookieJar(CookieJar.NO_COOKIES) @@ -94,7 +96,15 @@ class NextcloudClient private constructor( .hostnameVerifier { _: String?, _: SSLSession? -> true } .fastFallback(true) .proxy(proxy) - .build() + .addNetworkInterceptor { chain -> + chain.proceed( + chain + .request() + .newBuilder() + .header("User-Agent", userAgent) + .build() + ) + }.build() } } @@ -191,13 +201,12 @@ class NextcloudClient private constructor( return result } - fun disabledRedirectClient(): OkHttpClient { - return client + fun disabledRedirectClient(): OkHttpClient = + client .newBuilder() .followRedirects(false) .authenticator(NextcloudAuthenticator(credentials)) .build() - } private fun setRedirectedDestinationHeader( method: OkHttpMethodBase, diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt b/library/src/main/java/com/nextcloud/common/WebDavUtils.kt similarity index 58% rename from library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt rename to library/src/main/java/com/nextcloud/common/WebDavUtils.kt index 85915e852..5e072c920 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils2.kt +++ b/library/src/main/java/com/nextcloud/common/WebDavUtils.kt @@ -1,24 +1,26 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ -package com.owncloud.android.lib.common.network +package com.nextcloud.common import android.net.Uri -import at.bitfire.dav4jvm.PropertyRegistry.register +import at.bitfire.dav4jvm.PropertyRegistry +import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.property.CreationDate import at.bitfire.dav4jvm.property.DisplayName import at.bitfire.dav4jvm.property.GetContentLength import at.bitfire.dav4jvm.property.GetContentType +import at.bitfire.dav4jvm.property.GetETag import at.bitfire.dav4jvm.property.ResourceType import com.google.gson.Gson +import com.owncloud.android.lib.common.network.WebdavEntry +import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.files.webdav.NCCreationTime import com.owncloud.android.lib.resources.files.webdav.NCEncrypted -import com.owncloud.android.lib.resources.files.webdav.NCEtag import com.owncloud.android.lib.resources.files.webdav.NCFavorite import com.owncloud.android.lib.resources.files.webdav.NCGetLastModified import com.owncloud.android.lib.resources.files.webdav.NCHidden @@ -53,13 +55,11 @@ import com.owncloud.android.lib.resources.files.webdav.OCLocalId import com.owncloud.android.lib.resources.files.webdav.OCOwnerDisplayName import com.owncloud.android.lib.resources.files.webdav.OCOwnerId import com.owncloud.android.lib.resources.files.webdav.OCSize -import org.apache.commons.httpclient.HttpMethod -import java.text.ParseException +import java.net.URLDecoder import java.text.SimpleDateFormat -import java.util.Date import java.util.Locale -object WebdavUtils2 { +object WebDavUtils { const val NAMESPACE_OC = "http://owncloud.org/ns" const val NAMESPACE_NC = "http://nextcloud.org/ns" @@ -86,7 +86,7 @@ object WebdavUtils2 { GetContentLength.NAME, NCGetLastModified.NAME, CreationDate.NAME, - NCEtag.NAME, + GetETag.NAME, NCPermissions.NAME, OCLocalId.NAME, OCId.NAME, @@ -129,7 +129,7 @@ object WebdavUtils2 { GetContentLength.NAME, NCGetLastModified.NAME, CreationDate.NAME, - NCEtag.NAME, + GetETag.NAME, NCPermissions.NAME, OCLocalId.NAME, OCId.NAME, @@ -188,64 +188,12 @@ object WebdavUtils2 { ) } - fun parseResponseDate(date: String?): Date? { - for (format in DATETIME_FORMATS) { - try { - date?.let { return format.parse(it) } - } catch (e: ParseException) { - // wrong format - } - } - return null - } - - /** - * Encodes a path according to URI RFC 2396. - * - * - * If the received path doesn't start with "/", the method adds it. - * - * @param remoteFilePath Path - * @return Encoded path according to RFC 2396, always starting with "/" - */ - fun encodePath(remoteFilePath: String?): String { - val encodedPath = Uri.encode(remoteFilePath, "/") - if (!encodedPath.startsWith("/")) { - return "/$encodedPath" - } - return encodedPath - } - - fun parseEtag(etag: String?): String { - if (etag.isNullOrEmpty()) { - return "" - } - return etag.removeSuffix("-gzip").removeSurrounding("\"") - } - - fun getEtagFromResponse(method: HttpMethod): String { - var eTag = method.getResponseHeader("OC-ETag") - if (eTag == null) { - eTag = method.getResponseHeader("oc-etag") - } - if (eTag == null) { - eTag = method.getResponseHeader("ETag") - } - if (eTag == null) { - eTag = method.getResponseHeader("etag") - } - if (eTag != null) { - return parseEtag(eTag.value) - } - return "" - } - fun registerCustomFactories() { val list = listOf( - NCCreationTime.Factory(), + // NCCreationTime.Factory(), NCEncrypted.Factory(), - NCEtag.Factory(), + GetETag.Factory(), NCFavorite.Factory(), NCGetLastModified.Factory(), NCHidden.Factory(), @@ -281,6 +229,189 @@ object WebdavUtils2 { OCOwnerId.Factory(), OCSize.Factory() ) - register(list) + PropertyRegistry.register(list) + } + + @Suppress("LongMethod") + fun parseResponse( + response: Response, + filesDavUri: Uri + ): RemoteFile { + val remoteFile = RemoteFile() + + val path = "/" + URLDecoder.decode(response.href.toString().substringAfter(filesDavUri.toString()), "UTF-8") + + for (property in response.properties) { + when (property) { + is DisplayName -> { + remoteFile.name = property.displayName ?: "" + } + + is GetContentLength -> { + remoteFile.length = property.contentLength + } + + is GetContentType -> { + remoteFile.mimeType = (property.type ?: "").toString() + } + + is ResourceType -> { + if (property.types.contains(ResourceType.COLLECTION)) { + remoteFile.mimeType = WebdavEntry.DIR_TYPE + } + } + + is NCCreationTime -> { + remoteFile.creationTimestamp = property.creationTime + } + + is NCEncrypted -> { + remoteFile.isEncrypted = property.encrypted + } + + is GetETag -> { + remoteFile.etag = property.eTag + } + + is NCFavorite -> { + remoteFile.isFavorite = property.favorite + } + + is NCGetLastModified -> { + remoteFile.modifiedTimestamp = property.lastModified + } + + is NCHidden -> { + remoteFile.hidden = property.hidden + } + + is NCLock -> { + remoteFile.isLocked = property.locked + } + + is NCLockOwner -> { + remoteFile.lockOwner = property.lockOwner + } + + is NCLockOwnerDisplayName -> { + remoteFile.lockOwnerDisplayName = property.lockOwnerDisplayName + } + + is NCLockOwnerEditor -> { + remoteFile.lockOwnerEditor = property.lockOwnerEditor + } + + is NCLockOwnerType -> { + remoteFile.lockType = property.lockOwnerType + } + + is NCLockTime -> { + remoteFile.lockTimestamp = property.lockTime + } + + is NCLockTimeout -> { + remoteFile.lockTimeout = property.lockTimeout + } + + is NCLockToken -> { + remoteFile.lockToken = property.lockToken + } + + is NCMetadataGPS -> { + remoteFile.geoLocation = property.geoLocation + } + + is NCMetadataLivePhoto -> { + remoteFile.livePhoto = property.livePhoto + } + + is NCMetadataPhotosGPS -> { + remoteFile.geoLocation = property.geoLocation + } + + is NCMetadataPhotosSize -> { + remoteFile.imageDimension = property.imageDimension + } + + is NCMetadataSize -> { + remoteFile.imageDimension = property.imageDimension + } + + is NCMountType -> { + remoteFile.mountType = property.mountType + } + + is NCNote -> { + remoteFile.note = property.note + } + + is NCPermissions -> { + remoteFile.permissions = property.permissions + } + + is NCPreview -> { + remoteFile.isHasPreview = property.preview + } + + is NCRichWorkspace -> { + remoteFile.richWorkspace = property.richWorkspace + } + + is NCSharees -> { + remoteFile.sharees = property.sharees + } + + is NCTags -> { + remoteFile.tags = property.tags + } + + is NCTrashbinDeletionTime -> { /* TODO */ } + + is NCTrashbinFilename -> { /* TODO */ } + + is NCTrashbinLocation -> { /* TODO */ } + + is NCUploadTime -> { + remoteFile.uploadTimestamp = property.uploadTime + } + + is OCCommentsUnread -> { + remoteFile.unreadCommentsCount = property.commentsCount + } + + is OCDisplayName -> { + remoteFile.name = property.displayName + } + + is OCId -> { + remoteFile.remoteId = property.id + } + + is OCLocalId -> { + remoteFile.localId = property.localId + } + + is OCOwnerDisplayName -> { + remoteFile.ownerDisplayName = property.ownerDisplayName ?: "" + } + + is OCOwnerId -> { + remoteFile.ownerId = property.ownerId ?: "" + } + + is OCSize -> { + remoteFile.size = property.size + } + } + } + + remoteFile.remotePath = path + + // displayName not set - get from path + if (remoteFile.name?.isEmpty() == true) { + remoteFile.name = path.substringAfterLast("/") + } + + return remoteFile } } diff --git a/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt b/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt index 8309dff0d..0cacee709 100644 --- a/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt +++ b/library/src/main/java/com/nextcloud/operations/PropFindMethod2.kt @@ -1,11 +1,10 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ package com.nextcloud.operations -class PropFindMethod2 { -} +class PropFindMethod2 diff --git a/library/src/main/java/com/nextcloud/operations/PropFindResult.kt b/library/src/main/java/com/nextcloud/operations/PropFindResult.kt index d70e7f23d..0dcfe646f 100644 --- a/library/src/main/java/com/nextcloud/operations/PropFindResult.kt +++ b/library/src/main/java/com/nextcloud/operations/PropFindResult.kt @@ -15,7 +15,5 @@ data class PropFindResult( var root: RemoteFile = RemoteFile(), val children: MutableList = mutableListOf() ) { - fun getContent(): List { - return listOf(root) + children - } + fun getContent(): List = listOf(root) + children } diff --git a/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt b/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt deleted file mode 100644 index 68511bd1f..000000000 --- a/library/src/main/java/com/owncloud/android/lib/common/DavMethod.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Nextcloud Android Library - * - * SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> - * SPDX-FileCopyrightText: 2023 Tobias Kaminsky - * SPDX-License-Identifier: MIT - */ -package com.nextcloud.common - -import android.net.Uri -import com.owncloud.android.lib.common.network.WebdavUtils2 -import okhttp3.HttpUrl -import okhttp3.OkHttpClient - -abstract class DavMethod(private val httpUrl: HttpUrl) { - fun execute(nextcloudClient: NextcloudClient): T { - // register custom property - WebdavUtils2.registerCustomFactories() - - return apply(nextcloudClient.disabledRedirectClient(), httpUrl, nextcloudClient.filesDavUri) - } - - abstract fun apply( - client: OkHttpClient, - httpUrl: HttpUrl, - filesDavUri: Uri - ): T -} diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt index 130964f2f..94cf68f37 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt @@ -1,15 +1,17 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+ZetaTom@users.noreply.github.com> + * SPDX-FileCopyrightText: 2026 Your Name * SPDX-License-Identifier: MIT */ package com.owncloud.android.lib.common.network import at.bitfire.dav4jvm.Property -enum class ExtendedProperties(val value: String, val namespace: String) { +enum class ExtendedProperties( + val value: String, + val namespace: String +) { CREATION_TIME("creation_time", WebdavUtils.NAMESPACE_NC), COMMENTS_READ_MARKER("readMarker", WebdavUtils.NAMESPACE_NC), DISPLAY_NAME("display-name", WebdavUtils.NAMESPACE_OC), @@ -54,7 +56,5 @@ enum class ExtendedProperties(val value: String, val namespace: String) { UNREAD_COMMENTS("comments-unread", WebdavUtils.NAMESPACE_OC), UPLOAD_TIME("upload_time", WebdavUtils.NAMESPACE_NC); - fun toPropertyName(): Property.Name { - return Property.Name(namespace, value) - } + fun toPropertyName(): Property.Name = Property.Name(namespace, value) } diff --git a/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt b/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt deleted file mode 100644 index cbb59085e..000000000 --- a/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils2.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Nextcloud Android Library - * - * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2017 Mario Danic - * SPDX-License-Identifier: MIT - */ -package com.owncloud.android.lib.common.utils - -import android.net.Uri -import at.bitfire.dav4jvm.Response -import at.bitfire.dav4jvm.property.DisplayName -import at.bitfire.dav4jvm.property.GetContentLength -import at.bitfire.dav4jvm.property.GetContentType -import at.bitfire.dav4jvm.property.ResourceType -import com.owncloud.android.lib.common.network.WebdavEntry -import com.owncloud.android.lib.resources.files.model.RemoteFile -import com.owncloud.android.lib.resources.files.webdav.NCCreationTime -import com.owncloud.android.lib.resources.files.webdav.NCEncrypted -import com.owncloud.android.lib.resources.files.webdav.NCEtag -import com.owncloud.android.lib.resources.files.webdav.NCFavorite -import com.owncloud.android.lib.resources.files.webdav.NCGetLastModified -import com.owncloud.android.lib.resources.files.webdav.NCHidden -import com.owncloud.android.lib.resources.files.webdav.NCLock -import com.owncloud.android.lib.resources.files.webdav.NCLockOwner -import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerDisplayName -import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerEditor -import com.owncloud.android.lib.resources.files.webdav.NCLockOwnerType -import com.owncloud.android.lib.resources.files.webdav.NCLockTime -import com.owncloud.android.lib.resources.files.webdav.NCLockTimeout -import com.owncloud.android.lib.resources.files.webdav.NCLockToken -import com.owncloud.android.lib.resources.files.webdav.NCMetadataGPS -import com.owncloud.android.lib.resources.files.webdav.NCMetadataLivePhoto -import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosGPS -import com.owncloud.android.lib.resources.files.webdav.NCMetadataPhotosSize -import com.owncloud.android.lib.resources.files.webdav.NCMetadataSize -import com.owncloud.android.lib.resources.files.webdav.NCMountType -import com.owncloud.android.lib.resources.files.webdav.NCNote -import com.owncloud.android.lib.resources.files.webdav.NCPermissions -import com.owncloud.android.lib.resources.files.webdav.NCPreview -import com.owncloud.android.lib.resources.files.webdav.NCRichWorkspace -import com.owncloud.android.lib.resources.files.webdav.NCSharees -import com.owncloud.android.lib.resources.files.webdav.NCTags -import com.owncloud.android.lib.resources.files.webdav.NCTrashbinDeletionTime -import com.owncloud.android.lib.resources.files.webdav.NCTrashbinFilename -import com.owncloud.android.lib.resources.files.webdav.NCTrashbinLocation -import com.owncloud.android.lib.resources.files.webdav.NCUploadTime -import com.owncloud.android.lib.resources.files.webdav.OCCommentsUnread -import com.owncloud.android.lib.resources.files.webdav.OCDisplayName -import com.owncloud.android.lib.resources.files.webdav.OCId -import com.owncloud.android.lib.resources.files.webdav.OCLocalId -import com.owncloud.android.lib.resources.files.webdav.OCOwnerDisplayName -import com.owncloud.android.lib.resources.files.webdav.OCOwnerId -import com.owncloud.android.lib.resources.files.webdav.OCSize -import org.apache.jackrabbit.webdav.MultiStatus -import java.net.URLDecoder - -/** - * WebDav helper. - */ -object WebDavFileUtils2 { - /** - * Read the data retrieved from the server about the contents of the target folder - * - * @param remoteData Full response got from the server with the data of the target - * folder and its direct children. - * @param filesDavUri uri to files webdav uri - * @return content of the target folder - */ - fun readData( - remoteData: MultiStatus, - filesDavUri: Uri, - isReadFolderOperation: Boolean, - isSearchOperation: Boolean - ): ArrayList { - val mFolderAndFiles = ArrayList() - var we: WebdavEntry - var start = 1 - if (isReadFolderOperation) { - we = - WebdavEntry( - remoteData.responses[0], - filesDavUri.encodedPath!! - ) - mFolderAndFiles.add(RemoteFile(we)) - } else { - start = 0 - } - - // loop to update every child - var remoteFile: RemoteFile - val responses = remoteData.responses - for (i in start until responses.size) { - // / new OCFile instance with the data from the server - we = WebdavEntry(responses[i], filesDavUri.encodedPath!!) - remoteFile = RemoteFile(we) - mFolderAndFiles.add(remoteFile) - } - return mFolderAndFiles - } - - fun readData( - responses: List, - filesDavUri: Uri - ): ArrayList { - val list = ArrayList() - for (response in responses) { - list.add(parseResponse(response, filesDavUri)) - } - return list - } - - fun parseResponse( - response: Response, - filesDavUri: Uri - ): RemoteFile { - val remoteFile = RemoteFile() - - val path = "/" + URLDecoder.decode(response.href.toString().substringAfter(filesDavUri.toString()), "UTF-8") - - for (property in response.properties) { - when (property) { - is DisplayName -> remoteFile.name = property.displayName ?: "" - is GetContentLength -> remoteFile.length = property.contentLength - is GetContentType -> remoteFile.mimeType = (property.type ?: "").toString() - is ResourceType -> - if (property.types.contains(ResourceType.COLLECTION)) { - remoteFile.mimeType = WebdavEntry.DIR_TYPE - } - - is NCCreationTime -> remoteFile.creationTimestamp = property.creationTime - is NCEncrypted -> remoteFile.isEncrypted = property.encrypted - is NCEtag -> remoteFile.etag = property.etag - is NCFavorite -> remoteFile.isFavorite = property.favorite - is NCGetLastModified -> remoteFile.modifiedTimestamp = property.lastModified - is NCHidden -> remoteFile.hidden = property.hidden - is NCLock -> remoteFile.isLocked = property.locked - is NCLockOwner -> remoteFile.lockOwner = property.lockOwner - is NCLockOwnerDisplayName -> remoteFile.lockOwnerDisplayName = property.lockOwnerDisplayName - is NCLockOwnerEditor -> remoteFile.lockOwnerEditor = property.lockOwnerEditor - is NCLockOwnerType -> remoteFile.lockType = property.lockOwnerType - is NCLockTime -> remoteFile.lockTimestamp = property.lockTime - is NCLockTimeout -> remoteFile.lockTimeout = property.lockTimeout - is NCLockToken -> remoteFile.lockToken = property.lockToken - is NCMetadataGPS -> remoteFile.geoLocation = property.geoLocation - is NCMetadataLivePhoto -> remoteFile.livePhoto = property.livePhoto - is NCMetadataPhotosGPS -> remoteFile.geoLocation = property.geoLocation - is NCMetadataPhotosSize -> remoteFile.imageDimension = property.imageDimension - is NCMetadataSize -> remoteFile.imageDimension = property.imageDimension - is NCMountType -> remoteFile.mountType = property.mountType - is NCNote -> remoteFile.note = property.note - is NCPermissions -> remoteFile.permissions = property.permissions - is NCPreview -> remoteFile.isHasPreview = property.preview - is NCRichWorkspace -> remoteFile.richWorkspace = property.richWorkspace - is NCSharees -> remoteFile.sharees = property.sharees - is NCTags -> remoteFile.tags = property.tags - is NCTrashbinDeletionTime -> { /* TODO */ } - is NCTrashbinFilename -> { /* TODO */ } - is NCTrashbinLocation -> { /* TODO */ } - is NCUploadTime -> remoteFile.uploadTimestamp = property.uploadTime - is OCCommentsUnread -> remoteFile.unreadCommentsCount = property.commentsCount - is OCDisplayName -> remoteFile.name = property.displayName - is OCId -> remoteFile.remoteId = property.id - is OCLocalId -> remoteFile.localId = property.localId - is OCOwnerDisplayName -> remoteFile.ownerDisplayName = property.ownerDisplayName ?: "" - is OCOwnerId -> remoteFile.ownerId = property.ownerId ?: "" - is OCSize -> remoteFile.size = property.size - } - } - - remoteFile.remotePath = path - - // displayName not set - get from path - if (remoteFile.name?.isEmpty() == true) { - remoteFile.name = path.substringAfterLast("/") - } - - return remoteFile - } -} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt index 70c04f59a..0d3ca352a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt @@ -10,15 +10,14 @@ import androidx.core.net.toUri import at.bitfire.dav4jvm.DavCollection import com.nextcloud.common.NextcloudClient import com.nextcloud.common.SessionTimeOut +import com.nextcloud.common.WebDavUtils import com.nextcloud.common.defaultSessionTimeOut import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.common.network.WebdavUtils -import com.owncloud.android.lib.common.network.WebdavUtils2 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.common.utils.WebDavFileUtils2 import com.owncloud.android.lib.resources.files.model.RemoteFile import okhttp3.HttpUrl.Companion.toHttpUrl import org.apache.commons.httpclient.HttpStatus @@ -27,98 +26,96 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod /** * Remote operation performing the read a file from the ownCloud server. - * + * * @author David A. Velasco * @author masensio */ class ReadFileRemoteOperation -/** - * Constructor - * - * @param remotePath Remote path of the file. - */ @JvmOverloads constructor( - private val mRemotePath: String?, - private val sessionTimeOut: SessionTimeOut = defaultSessionTimeOut -) : RemoteOperation() { - /** - * Performs the read operation. - * - * @param client Client object to communicate with the remote ownCloud server. - */ - override fun run(client: OwnCloudClient): RemoteOperationResult { - var propfind: PropFindMethod? = null - var result: RemoteOperationResult + @JvmOverloads + constructor( + private val mRemotePath: String?, + private val sessionTimeOut: SessionTimeOut = defaultSessionTimeOut + ) : RemoteOperation() { + @Suppress("Detekt.TooGenericExceptionCaught") // legacy code + override fun run(client: OwnCloudClient): RemoteOperationResult { + var propfind: PropFindMethod? = null + var result: RemoteOperationResult - /** take the duty of check the server for the current state of the file there */ - try { - // remote request - propfind = PropFindMethod( - client.getFilesDavUri(mRemotePath), - WebdavUtils.getFilePropSet(), // PropFind Properties - DavConstants.DEPTH_0 - ) - val status: Int - status = client.executeMethod( - propfind, - sessionTimeOut.readTimeOut, - sessionTimeOut.connectionTimeOut - ) + try { + // remote request + propfind = + PropFindMethod( + client.getFilesDavUri(mRemotePath), + WebdavUtils.getFilePropSet(), // PropFind Properties + DavConstants.DEPTH_0 + ) + val status: Int + status = + client.executeMethod( + propfind, + sessionTimeOut.readTimeOut, + sessionTimeOut.connectionTimeOut + ) - val isSuccess = (status == HttpStatus.SC_MULTI_STATUS || - status == HttpStatus.SC_OK + val isSuccess = ( + status == HttpStatus.SC_MULTI_STATUS || + status == HttpStatus.SC_OK ) - if (isSuccess) { - // Parse response - val resp = propfind.getResponseBodyAsMultiStatus() - val we = WebdavEntry( - resp.getResponses()[0], - client.getFilesDavUri().getEncodedPath()!! + if (isSuccess) { + // Parse response + val resp = propfind.getResponseBodyAsMultiStatus() + val we = + WebdavEntry( + resp.getResponses()[0], + client.getFilesDavUri().getEncodedPath()!! + ) + // Result of the operation + result = RemoteOperationResult(true, propfind) + result.resultData = RemoteFile(we) + } else { + result = RemoteOperationResult(false, propfind) + client.exhaustResponse(propfind.getResponseBodyAsStream()) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Read file " + mRemotePath + " failed: " + result.getLogMessage(), + result.getException() ) - // Result of the operation - result = RemoteOperationResult(true, propfind) - result.resultData = RemoteFile(we) - } else { - result = RemoteOperationResult(false, propfind) - client.exhaustResponse(propfind.getResponseBodyAsStream()) - } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, "Read file " + mRemotePath + " failed: " + result.getLogMessage(), - result.getException() - ) - } finally { - if (propfind != null) { - propfind.releaseConnection() + } finally { + if (propfind != null) { + propfind.releaseConnection() + } } + return result } - return result - } - override fun run(client: NextcloudClient): RemoteOperationResult { - var result: RemoteFile? = null - val location = client.getFilesDavUri(mRemotePath!!).toHttpUrl() + @Suppress("SpreadOperator") + override fun run(client: NextcloudClient): RemoteOperationResult { + WebDavUtils.registerCustomFactories() - val davCollection = DavCollection(client.disabledRedirectClient(), location) + var result: RemoteFile? = null + val location = client.getFilesDavUri(mRemotePath!!).toHttpUrl() - davCollection.propfind(depth = 1, *WebdavUtils2.PROPERTYSETS.ALL) { response, relation -> - // This callback will be called for every file in the folder. - // Use `response.properties` to access the successfully retrieved properties. - if (response.isSuccess()) { - result = WebDavFileUtils2.parseResponse(response, client.getFilesDavUri("/").toUri()) + val davCollection = DavCollection(client.disabledRedirectClient(), location) + + davCollection.propfind(depth = 1, *WebDavUtils.PROPERTYSETS.ALL) { response, _ -> + if (response.isSuccess()) { + result = WebDavUtils.parseResponse(response, client.getFilesDavUri("/").toUri()) + } } - } - return if (result == null) { - RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) - } else { - RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { - resultData = result + return if (result == null) { + RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) + } else { + RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { + resultData = result + } } } - } - companion object { - private val TAG: String = ReadFileRemoteOperation::class.java.getSimpleName() + companion object { + private val TAG: String = ReadFileRemoteOperation::class.java.getSimpleName() + } } -} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index c16423dce..cb3f2c9d4 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -22,7 +22,9 @@ import java.io.Serializable * * @author masensio */ -class RemoteFile() : Parcelable, Serializable { +class RemoteFile() : + Parcelable, + Serializable { var remotePath: String? = null var mimeType: String? = null var length: Long = 0 @@ -41,7 +43,7 @@ class RemoteFile() : Parcelable, Serializable { var ownerDisplayName: String? = null var unreadCommentsCount = 0 var isHasPreview = false - var note: String? = null + var note: String? = "" var name: String? = null var sharees: Array? = null var richWorkspace: String? = null @@ -60,8 +62,6 @@ class RemoteFile() : Parcelable, Serializable { var livePhoto: String? = null var fileDownloadLimit: List = emptyList() - - /** * Create new [RemoteFile] with given path. * diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt index e70b22ab5..032cfaa2c 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -9,15 +9,21 @@ package com.owncloud.android.lib.resources.files.webdav import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser -class NCCreationTime private constructor(val creationTime: Long) : Property { +class NCCreationTime private constructor( + val creationTime: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { - return NCCreationTime(parser.text.toLong()) + XmlUtils.readText(parser)?.let { date -> + return NCCreationTime(date.toLong()) + } + return NCCreationTime(0) } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt index 8a0d6e02d..0e87bb2f1 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCEncrypted private constructor(val encrypted: Boolean) : Property { +class NCEncrypted private constructor( + val encrypted: Boolean +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCEncrypted("1" == text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt index 53bed44d3..d2df8119d 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -9,17 +9,20 @@ package com.owncloud.android.lib.resources.files.webdav import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import at.bitfire.dav4jvm.XmlUtils.NS_WEBDAV import com.owncloud.android.lib.common.network.WebdavUtils import org.xmlpull.v1.XmlPullParser -class NCEtag private constructor(val etag: String?) : Property { +class NCEtag private constructor( + val etag: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): NCEtag { // - parser.text?.let { rawEtag -> + XmlUtils.readText(parser)?.let { rawEtag -> return NCEtag(WebdavUtils.parseEtag(rawEtag)) } return NCEtag(null) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt index 73af004c0..11e4e7e0b 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCFavorite private constructor(val favorite: Boolean) : Property { +class NCFavorite private constructor( + val favorite: Boolean +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCFavorite("1" == text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt index 4f54c2c9d..ef5eb2bf9 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCGetLastModified.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -9,17 +9,20 @@ package com.owncloud.android.lib.resources.files.webdav import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import at.bitfire.dav4jvm.XmlUtils.NS_WEBDAV import com.owncloud.android.lib.common.network.WebdavUtils import org.xmlpull.v1.XmlPullParser -class NCGetLastModified private constructor(val lastModified: Long) : Property { +class NCGetLastModified private constructor( + val lastModified: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): NCGetLastModified { // - parser.text?.let { rawDate -> + XmlUtils.readText(parser)?.let { rawDate -> val date = WebdavUtils.parseResponseDate(rawDate) if (date != null) { return NCGetLastModified(date.time) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt index 9cf00d2e6..5b40ea92a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCHidden.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCHidden private constructor(val hidden: Boolean) : Property { +class NCHidden private constructor( + val hidden: Boolean +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCHidden("true" == text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt index e0f02d17b..48d479ca6 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLock.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLock private constructor(val locked: Boolean) : Property { +class NCLock private constructor( + val locked: Boolean +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCLock("1" == text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt index 25ce48114..cb7431661 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwner.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockOwner private constructor(val lockOwner: String?) : Property { +class NCLockOwner private constructor( + val lockOwner: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockOwner(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt index 415429998..42dd6039a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerDisplayName.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockOwnerDisplayName private constructor(val lockOwnerDisplayName: String) : Property { +class NCLockOwnerDisplayName private constructor( + val lockOwnerDisplayName: String +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockOwnerDisplayName(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt index e4cb197cf..1ad50f1ba 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerEditor.kt @@ -11,18 +11,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockOwnerEditor private constructor(val lockOwnerEditor: String?) : Property { +class NCLockOwnerEditor private constructor( + val lockOwnerEditor: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockOwnerEditor(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt index abe480d81..cc2884a24 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockOwnerType.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,19 +10,22 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.files.model.FileLockType import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockOwnerType private constructor(val lockOwnerType: FileLockType?) : Property { +class NCLockOwnerType private constructor( + val lockOwnerType: FileLockType? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockOwnerType(FileLockType.fromValue(text.toInt())) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt index 5431dbee9..009c98f66 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTime.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -9,15 +9,18 @@ package com.owncloud.android.lib.resources.files.webdav import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser -class NCLockTime private constructor(val lockTime: Long) : Property { +class NCLockTime private constructor( + val lockTime: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { - parser.text?.let { date -> + XmlUtils.readText(parser)?.let { date -> return NCLockTime(date.toLong()) } return NCLockTime(0) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt index 24f124636..473f926ae 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockTimeout.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockTimeout private constructor(val lockTimeout: Long) : Property { +class NCLockTimeout private constructor( + val lockTimeout: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockTimeout(text.toLong()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt index 86ec51eb0..d14aca518 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCLockToken.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCLockToken private constructor(val lockToken: String?) : Property { +class NCLockToken private constructor( + val lockToken: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCLockToken(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt index 03ca75886..0f8c5d652 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataGPS.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,6 +10,7 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.google.gson.Gson import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.files.model.GeoLocation @@ -17,13 +18,15 @@ import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCMetadataGPS private constructor(val geoLocation: GeoLocation?) : Property { +class NCMetadataGPS private constructor( + val geoLocation: GeoLocation? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { val geoLocation = Gson().fromJson(text, GeoLocation::class.java) return NCMetadataGPS(geoLocation) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt index 52007252f..dede31284 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataLivePhoto.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCMetadataLivePhoto private constructor(val livePhoto: String?) : Property { +class NCMetadataLivePhoto private constructor( + val livePhoto: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCMetadataLivePhoto(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt index 7b93c94a0..5a4dcfc3b 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosGPS.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -11,19 +11,20 @@ import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory import at.bitfire.dav4jvm.XmlUtils.propertyName +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.files.model.GeoLocation import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCMetadataPhotosGPS private constructor(val geoLocation: GeoLocation) : Property { +class NCMetadataPhotosGPS private constructor( + val geoLocation: GeoLocation +) : Property { class Factory : PropertyFactory { override fun getName() = NAME - override fun create(parser: XmlPullParser): Property { - return NCMetadataPhotosGPS(parseText(parser)) - } + override fun create(parser: XmlPullParser): Property = NCMetadataPhotosGPS(parseText(parser)) @Suppress("NestedBlockDepth") private fun parseText(parser: XmlPullParser): GeoLocation { @@ -37,8 +38,8 @@ class NCMetadataPhotosGPS private constructor(val geoLocation: GeoLocation) : Pr while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { if (eventType != XmlPullParser.TEXT) { when (parser.propertyName().name) { - "latitude" -> parser.text?.let { latitude = it.toDouble() } - "longitude" -> parser.text?.let { longitude = it.toDouble() } + "latitude" -> readText(parser)?.let { latitude = it.toDouble() } + "longitude" -> readText(parser)?.let { longitude = it.toDouble() } } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt index a52a842af..64d7ad699 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataPhotosSize.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -11,19 +11,20 @@ import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory import at.bitfire.dav4jvm.XmlUtils.propertyName +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.files.model.ImageDimension import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCMetadataPhotosSize private constructor(val imageDimension: ImageDimension) : Property { +class NCMetadataPhotosSize private constructor( + val imageDimension: ImageDimension +) : Property { class Factory : PropertyFactory { override fun getName() = NAME - override fun create(parser: XmlPullParser): Property { - return NCMetadataPhotosSize(parseText(parser)) - } + override fun create(parser: XmlPullParser): Property = NCMetadataPhotosSize(parseText(parser)) @Suppress("NestedBlockDepth") private fun parseText(parser: XmlPullParser): ImageDimension { @@ -37,8 +38,8 @@ class NCMetadataPhotosSize private constructor(val imageDimension: ImageDimensio while (eventType != XmlPullParser.END_TAG || parser.depth != depth) { if (eventType != XmlPullParser.TEXT) { when (parser.propertyName().name) { - "width" -> parser.text?.let { width = it.toFloat() } - "height" -> parser.text?.let { height = it.toFloat() } + "width" -> readText(parser)?.let { width = it.toFloat() } + "height" -> readText(parser)?.let { height = it.toFloat() } } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt index 510392202..d691ba32b 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMetadataSize.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,6 +10,7 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.google.gson.Gson import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.files.model.ImageDimension @@ -17,13 +18,15 @@ import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCMetadataSize private constructor(val imageDimension: ImageDimension?) : Property { +class NCMetadataSize private constructor( + val imageDimension: ImageDimension? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { val imageDimension = Gson().fromJson(text, ImageDimension::class.java) return NCMetadataSize(imageDimension) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt index 0eb7bca11..3fdcc6bd7 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -9,17 +9,20 @@ package com.owncloud.android.lib.resources.files.webdav import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.common.network.WebdavEntry import org.xmlpull.v1.XmlPullParser -class NCMountType private constructor(val mountType: WebdavEntry.MountType) : Property { +class NCMountType private constructor( + val mountType: WebdavEntry.MountType +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): NCMountType { // (#PCDATA) > - val type = parser.text + val type = XmlUtils.readText(parser) return NCMountType( when (type) { "external" -> WebdavEntry.MountType.EXTERNAL diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt index d6fb2a2da..f4cc01e8a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCNote.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCNote private constructor(val note: String) : Property { +class NCNote private constructor( + val note: String +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCNote(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt index 555ad2c23..f7b61d030 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCPermissions private constructor(val permissions: String?) : Property { +class NCPermissions private constructor( + val permissions: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCPermissions(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt index 66aefcdde..76cf95ad2 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCPreview private constructor(val preview: Boolean) : Property { +class NCPreview private constructor( + val preview: Boolean +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCPreview(text.toBoolean()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt index 8f42df821..545ba497c 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCRichWorkspace private constructor(val richWorkspace: String?) : Property { +class NCRichWorkspace private constructor( + val richWorkspace: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): NCRichWorkspace { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCRichWorkspace(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt index 05109fd07..4c7957067 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharees.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -11,6 +11,7 @@ import androidx.annotation.VisibleForTesting import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory import at.bitfire.dav4jvm.XmlUtils.propertyName +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.shares.ShareType import com.owncloud.android.lib.resources.shares.ShareeUser @@ -18,7 +19,9 @@ import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCSharees private constructor(val sharees: Array) : Property { +class NCSharees private constructor( + val sharees: Array +) : Property { class Factory : PropertyFactory { override fun getName() = NAME @@ -79,15 +82,15 @@ class NCSharees private constructor(val sharees: Array) : Property { if (eventType != XmlPullParser.TEXT) { when (parser.propertyName()) { ExtendedProperties.SHAREES_ID.toPropertyName() -> { - userId = parser.text + userId = readText(parser) } ExtendedProperties.SHAREES_DISPLAY_NAME.toPropertyName() -> { - displayName = parser.text + displayName = readText(parser) } ExtendedProperties.SHAREES_SHARE_TYPE.toPropertyName() -> { - shareType = ShareType.fromValue(parser.text?.toInt() ?: 0) + shareType = ShareType.fromValue(readText(parser)?.toInt() ?: 0) } } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt index a412c8bf5..c7d861d0c 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTags.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -11,13 +11,16 @@ import androidx.annotation.VisibleForTesting import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory import at.bitfire.dav4jvm.XmlUtils.propertyName +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import com.owncloud.android.lib.resources.tags.Tag import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCTags private constructor(val tags: Array) : Property { +class NCTags private constructor( + val tags: Array +) : Property { class Factory : PropertyFactory { override fun getName() = NAME @@ -77,19 +80,19 @@ class NCTags private constructor(val tags: Array) : Property { if (eventType != XmlPullParser.TEXT) { when (parser.propertyName().toString()) { "http://nextcloud.org/ns:id" -> { - id = parser.text + id = readText(parser).orEmpty() } "http://nextcloud.org/ns:name" -> { - name = parser.text + name = readText(parser).orEmpty() } "http://nextcloud.org/ns:color" -> { - color = parser.text + color = readText(parser).orEmpty() } } } - + eventType = parser.next() } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt index 489449ded..f69ae649b 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinDeletionTime.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCTrashbinDeletionTime private constructor(val deletionTime: Long) : Property { +class NCTrashbinDeletionTime private constructor( + val deletionTime: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCTrashbinDeletionTime(text.toLong()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt index 782b5b96b..2ece1305e 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinFilename.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCTrashbinFilename private constructor(val originalLocation: String?) : Property { +class NCTrashbinFilename private constructor( + val originalLocation: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCTrashbinFilename(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt index 3ac92fb20..693d078b0 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCTrashbinLocation.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCTrashbinLocation private constructor(val originalLocation: String?) : Property { +class NCTrashbinLocation private constructor( + val originalLocation: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return NCTrashbinLocation(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt index e7ea1bff8..3255e464b 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCUploadTime.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class NCUploadTime private constructor(val uploadTime: Long) : Property { +class NCUploadTime private constructor( + val uploadTime: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = XmlUtils.readText(parser) if (!text.isNullOrEmpty()) { return NCUploadTime(text.toLong()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt index bebc9feba..53d12601a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCCommentsUnread.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCCommentsUnread private constructor(val commentsCount: Int) : Property { +class OCCommentsUnread private constructor( + val commentsCount: Int +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCCommentsUnread(text.toInt()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt index 4d1afe7d8..9d2759927 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCDisplayName.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCDisplayName private constructor(val displayName: String) : Property { +class OCDisplayName private constructor( + val displayName: String +) : Property { class Factory : PropertyFactory { override fun getName(): Property.Name = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCDisplayName(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt index 469f4e457..dc2217cc9 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCId private constructor(val id: String?) : Property { +class OCId private constructor( + val id: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCId(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt index 65f35046b..c2938c651 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCLocalId.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCLocalId private constructor(val localId: Long) : Property { +class OCLocalId private constructor( + val localId: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCLocalId(text.toLong()) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt index 1e724a2b5..c3203e36a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCOwnerDisplayName private constructor(val ownerDisplayName: String?) : Property { +class OCOwnerDisplayName private constructor( + val ownerDisplayName: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCOwnerDisplayName(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt index f01223a53..510c04960 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCOwnerId private constructor(val ownerId: String?) : Property { +class OCOwnerId private constructor( + val ownerId: String? +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCOwnerId(text) } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt index f73c90d16..50fa014a1 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt @@ -1,7 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2026 Your Name + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky * SPDX-License-Identifier: MIT */ @@ -10,18 +10,21 @@ package com.owncloud.android.lib.resources.files.webdav import android.util.Log import at.bitfire.dav4jvm.Property import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.readText import com.owncloud.android.lib.common.network.ExtendedProperties import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import java.io.IOException -class OCSize private constructor(val size: Long) : Property { +class OCSize private constructor( + val size: Long +) : Property { class Factory : PropertyFactory { override fun getName() = NAME override fun create(parser: XmlPullParser): Property { try { - val text = parser.text + val text = readText(parser) if (!text.isNullOrEmpty()) { return OCSize(text.toLong()) } From af07b2063d44591df1f597118f86c00a12a71e4c Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 25 Aug 2026 12:52:23 +0200 Subject: [PATCH 4/6] wip Signed-off-by: tobiasKaminsky --- .../main/java/com/nextcloud/common/NextcloudAuthenticator.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt index 4b751ff73..1b1528e33 100644 --- a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt +++ b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.kt @@ -1,8 +1,7 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2022 Tobias Kaminsky + * SPDX-FileCopyrightText: 2026 Your Name * SPDX-License-Identifier: MIT */ package com.nextcloud.common From 4b1f7d5af7bbf8611f463342eaccc75ddf9145f8 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 25 Aug 2026 14:55:51 +0200 Subject: [PATCH 5/6] wip Signed-off-by: tobiasKaminsky --- .../search/UnifiedSearchRemoteOperationIT.kt | 5 +-- .../files/SearchRemoteOperationIT.java | 4 +- .../java/com/nextcloud/common/WebDavUtils.kt | 18 ++++----- .../lib/common/network/ExtendedProperties.kt | 1 - .../files/ReadFileRemoteOperation.kt | 24 +++++++----- .../resources/files/webdav/NCCreationDate.kt | 39 +++++++++++++++++++ .../resources/files/webdav/NCCreationTime.kt | 34 ---------------- 7 files changed, 65 insertions(+), 60 deletions(-) create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationDate.kt delete mode 100644 library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt diff --git a/library/src/androidTest/java/com/nextcloud/android/lib/resources/search/UnifiedSearchRemoteOperationIT.kt b/library/src/androidTest/java/com/nextcloud/android/lib/resources/search/UnifiedSearchRemoteOperationIT.kt index 17962eed6..9fc44f763 100644 --- a/library/src/androidTest/java/com/nextcloud/android/lib/resources/search/UnifiedSearchRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/nextcloud/android/lib/resources/search/UnifiedSearchRemoteOperationIT.kt @@ -10,7 +10,6 @@ package com.nextcloud.android.lib.resources.search import com.owncloud.android.AbstractIT import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation -import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -48,8 +47,8 @@ class UnifiedSearchRemoteOperationIT : AbstractIT() { assertTrue(CreateFolderRemoteOperation(remotePath, true).execute(client).isSuccess) val remoteFile = ReadFileRemoteOperation(remotePath) - .execute(client) - .data[0] as RemoteFile + .execute(nextcloudClient) + .resultData val fileId = remoteFile.localId val result = UnifiedSearchRemoteOperation("files", "test").execute(nextcloudClient) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java index d861468ee..94577c8e9 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/SearchRemoteOperationIT.java @@ -57,10 +57,10 @@ public void testSearchByFileIdEmpty() { public void testSearchByFileIdSuccess() { assertTrue(new CreateFolderRemoteOperation("/test/", true).execute(client).isSuccess()); - RemoteOperationResult readFile = new ReadFileRemoteOperation("/test/").execute(nextcloudClient); + RemoteOperationResult readFile = new ReadFileRemoteOperation("/test/").execute(nextcloudClient); assertTrue(readFile.isSuccess()); - RemoteFile remoteFile = ((RemoteFile) readFile.getSingleData()); + RemoteFile remoteFile = readFile.getResultData(); SearchRemoteOperation sut = new SearchRemoteOperation(String.valueOf(remoteFile.getLocalId()), SearchRemoteOperation.SearchType.FILE_ID_SEARCH, false, diff --git a/library/src/main/java/com/nextcloud/common/WebDavUtils.kt b/library/src/main/java/com/nextcloud/common/WebDavUtils.kt index 5e072c920..5dfceddeb 100644 --- a/library/src/main/java/com/nextcloud/common/WebDavUtils.kt +++ b/library/src/main/java/com/nextcloud/common/WebDavUtils.kt @@ -10,7 +10,6 @@ package com.nextcloud.common import android.net.Uri import at.bitfire.dav4jvm.PropertyRegistry import at.bitfire.dav4jvm.Response -import at.bitfire.dav4jvm.property.CreationDate import at.bitfire.dav4jvm.property.DisplayName import at.bitfire.dav4jvm.property.GetContentLength import at.bitfire.dav4jvm.property.GetContentType @@ -19,7 +18,7 @@ import at.bitfire.dav4jvm.property.ResourceType import com.google.gson.Gson import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.resources.files.model.RemoteFile -import com.owncloud.android.lib.resources.files.webdav.NCCreationTime +import com.owncloud.android.lib.resources.files.webdav.NCCreationDate import com.owncloud.android.lib.resources.files.webdav.NCEncrypted import com.owncloud.android.lib.resources.files.webdav.NCFavorite import com.owncloud.android.lib.resources.files.webdav.NCGetLastModified @@ -85,7 +84,7 @@ object WebDavUtils { ResourceType.NAME, GetContentLength.NAME, NCGetLastModified.NAME, - CreationDate.NAME, + NCCreationDate.NAME, GetETag.NAME, NCPermissions.NAME, OCLocalId.NAME, @@ -101,7 +100,7 @@ object WebDavUtils { NCNote.NAME, NCSharees.NAME, NCRichWorkspace.NAME, - NCCreationTime.NAME, + NCCreationDate.NAME, NCUploadTime.NAME, NCLock.NAME, NCLockOwnerType.NAME, @@ -128,7 +127,7 @@ object WebDavUtils { ResourceType.NAME, GetContentLength.NAME, NCGetLastModified.NAME, - CreationDate.NAME, + NCCreationDate.NAME, GetETag.NAME, NCPermissions.NAME, OCLocalId.NAME, @@ -137,7 +136,6 @@ object WebDavUtils { NCFavorite.NAME, NCPreview.NAME, NCSharees.NAME, - NCCreationTime.NAME, NCUploadTime.NAME, NCLock.NAME, NCLockOwnerType.NAME, @@ -175,7 +173,7 @@ object WebDavUtils { ResourceType.NAME, GetContentLength.NAME, NCGetLastModified.NAME, - CreationDate.NAME, + NCCreationDate.NAME, OCId.NAME, OCSize.NAME ) @@ -191,7 +189,7 @@ object WebDavUtils { fun registerCustomFactories() { val list = listOf( - // NCCreationTime.Factory(), + NCCreationDate.Factory(), NCEncrypted.Factory(), GetETag.Factory(), NCFavorite.Factory(), @@ -261,8 +259,8 @@ object WebDavUtils { } } - is NCCreationTime -> { - remoteFile.creationTimestamp = property.creationTime + is NCCreationDate -> { + remoteFile.creationTimestamp = property.creationDate } is NCEncrypted -> { diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt index 94cf68f37..ce48ddf77 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/ExtendedProperties.kt @@ -12,7 +12,6 @@ enum class ExtendedProperties( val value: String, val namespace: String ) { - CREATION_TIME("creation_time", WebdavUtils.NAMESPACE_NC), COMMENTS_READ_MARKER("readMarker", WebdavUtils.NAMESPACE_NC), DISPLAY_NAME("display-name", WebdavUtils.NAMESPACE_OC), FAVORITE("favorite", WebdavUtils.NAMESPACE_OC), diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt index 0d3ca352a..c731f5ed0 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperation.kt @@ -91,7 +91,7 @@ class ReadFileRemoteOperation return result } - @Suppress("SpreadOperator") + @Suppress("SpreadOperator", "Detekt.TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { WebDavUtils.registerCustomFactories() @@ -100,18 +100,22 @@ class ReadFileRemoteOperation val davCollection = DavCollection(client.disabledRedirectClient(), location) - davCollection.propfind(depth = 1, *WebDavUtils.PROPERTYSETS.ALL) { response, _ -> - if (response.isSuccess()) { - result = WebDavUtils.parseResponse(response, client.getFilesDavUri("/").toUri()) + try { + davCollection.propfind(depth = 1, *WebDavUtils.PROPERTYSETS.ALL) { response, _ -> + if (response.isSuccess()) { + result = WebDavUtils.parseResponse(response, client.getFilesDavUri("/").toUri()) + } } - } - return if (result == null) { - RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) - } else { - RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { - resultData = result + return if (result == null) { + RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) + } else { + RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { + resultData = result + } } + } catch (e: Exception) { + return RemoteOperationResult(e) } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationDate.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationDate.kt new file mode 100644 index 000000000..bd1a91487 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationDate.kt @@ -0,0 +1,39 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files.webdav + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils +import at.bitfire.dav4jvm.XmlUtils.NS_WEBDAV +import com.owncloud.android.lib.common.network.WebdavUtils +import org.xmlpull.v1.XmlPullParser + +class NCCreationDate private constructor( + val creationDate: Long +) : Property { + class Factory : PropertyFactory { + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCCreationDate { + XmlUtils.readText(parser)?.let { rawDate -> + val date = WebdavUtils.parseResponseDate(rawDate) + if (date != null) { + return NCCreationDate(date.time / SECOND_IN_MILLIS) + } + } + return NCCreationDate(0) + } + } + + companion object { + @JvmField + val NAME = Property.Name(NS_WEBDAV, "creationdate") + const val SECOND_IN_MILLIS = 1000 + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt deleted file mode 100644 index 032cfaa2c..000000000 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCCreationTime.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Nextcloud Android Library - * - * SPDX-FileCopyrightText: 2026 Tobias Kaminsky - * SPDX-License-Identifier: MIT - */ - -package com.owncloud.android.lib.resources.files.webdav - -import at.bitfire.dav4jvm.Property -import at.bitfire.dav4jvm.PropertyFactory -import at.bitfire.dav4jvm.XmlUtils -import com.owncloud.android.lib.common.network.ExtendedProperties -import org.xmlpull.v1.XmlPullParser - -class NCCreationTime private constructor( - val creationTime: Long -) : Property { - class Factory : PropertyFactory { - override fun getName() = NAME - - override fun create(parser: XmlPullParser): Property { - XmlUtils.readText(parser)?.let { date -> - return NCCreationTime(date.toLong()) - } - return NCCreationTime(0) - } - } - - companion object { - @JvmField - val NAME = ExtendedProperties.CREATION_TIME.toPropertyName() - } -} From b28f23619072505c1990fca376f9d6a70c3c17ad Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 27 Aug 2026 14:25:21 +0200 Subject: [PATCH 6/6] fix unit test Signed-off-by: tobiasKaminsky --- .../src/test/java/com/nextcloud/common/NextcloudClientTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt b/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt index 3acb691cc..1de00c2e6 100644 --- a/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt +++ b/library/src/test/java/com/nextcloud/common/NextcloudClientTest.kt @@ -55,7 +55,7 @@ class NextcloudClientTest { val exception = RuntimeException("test exception") val operation = object : RemoteOperation() { - override suspend fun run(client: NextcloudClient?): RemoteOperationResult = throw exception + override fun run(client: NextcloudClient?): RemoteOperationResult = throw exception } // WHEN