diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..e25885c34e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dav4jvm"] + path = dav4jvm + url = /home/tobi/projekt/github/bitfireAT/dav4jvm diff --git a/dav4jvm b/dav4jvm new file mode 160000 index 0000000000..c61e4b0c80 --- /dev/null +++ b/dav4jvm @@ -0,0 +1 @@ +Subproject commit c61e4b0c80a5a8de1df99b4997445bb323d3ea3d diff --git a/library/build.gradle b/library/build.gradle index e7bf969751..afa03efba9 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -50,8 +50,8 @@ configurations { dependencies { implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5' api 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10' - implementation 'com.gitlab.bitfireAT:dav4jvm:2.1.3' // in transition phase, we use old and new libs - implementation group: 'com.google.code.gson', name: 'gson', version: '2.10' + implementation 'com.github.bitfireAT:dav4jvm:2.2' // in transition phase, we use old and new libs + implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.1' implementation 'androidx.annotation:annotation:1.5.0' compileOnly 'com.google.code.findbugs:annotations:3.0.1u2' diff --git a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java index fe42dbde55..d2c9f673c2 100644 --- a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -121,6 +121,7 @@ public static void beforeAll() throws InterruptedException, String userId = loginName; // for test same as userId String credentials = Credentials.basic(loginName, password); nextcloudClient = new NextcloudClient(url, userId, credentials, context); + nextcloudClient.setUserId(userId); waitForServer(client, url); testConnection(); diff --git a/library/src/androidTest/java/com/owncloud/android/Dav4JVM.kt b/library/src/androidTest/java/com/owncloud/android/Dav4JVM.kt new file mode 100644 index 0000000000..cb2c73b622 --- /dev/null +++ b/library/src/androidTest/java/com/owncloud/android/Dav4JVM.kt @@ -0,0 +1,247 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android + +import at.bitfire.dav4jvm.DavResource +import at.bitfire.dav4jvm.Response +import at.bitfire.dav4jvm.property.CreationDate +import com.nextcloud.common.NextcloudAuthenticator +import com.owncloud.android.lib.common.network.WebdavUtils +import com.owncloud.android.lib.common.utils.WebDavFileUtils +import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation +import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation +import com.owncloud.android.lib.resources.files.SearchRemoteOperation +import com.owncloud.android.lib.resources.files.ToggleFavoriteRemoteOperation +import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation +import com.owncloud.android.lib.resources.files.model.RemoteFile +import com.owncloud.android.lib.resources.files.webdav.NCFavorite +import com.owncloud.android.lib.resources.shares.CreateShareRemoteOperation +import com.owncloud.android.lib.resources.shares.OCShare +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.lib.resources.status.OCCapability +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.apache.jackrabbit.webdav.DavConstants +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.IOException + +/* +can be removed after fully switching to dav4jvm as other tests should cover it + */ +class Dav4JVM : AbstractIT() { + @Test + @Throws(IOException::class) + fun singlePropfind() { + val path = "/testFolder/" + + // create folder + CreateFolderRemoteOperation( + path, + true + ).execute(client).isSuccess + + // verify folder + assertTrue(ReadFolderRemoteOperation(path).execute(client).isSuccess) + + // add favorite + assertTrue(ToggleFavoriteRemoteOperation(true, path).execute(client).isSuccess) + + // share it + assertTrue( + CreateShareRemoteOperation( + path, + ShareType.USER, + "admin", + false, + "", + OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER, + true + ).execute(client) + .isSuccess + ) + + // do old read folder operation to compare data against it + val result = ReadFolderRemoteOperation(path).execute(client).data as List + val oldRemoteFile = result[0] + + // new + val httpUrl = (nextcloudClient.filesDavUri.toString() + path).toHttpUrl() + + var davResponse: Response? = null + + val memberElements: MutableList = ArrayList() + var rootElement: Response? = null + + // disable redirect + val client = nextcloudClient.client + .newBuilder() + .followRedirects(false) + .authenticator(NextcloudAuthenticator(nextcloudClient.credentials, "Authorization")) + .build() + + // register custom property + WebdavUtils.registerCustomFactories() + + DavResource(client, httpUrl) + .propfind( + DavConstants.DEPTH_1, + *WebdavUtils.getAllPropertiesList() + ) { response: Response, hrefRelation: Response.HrefRelation? -> + davResponse = response + when (hrefRelation) { + Response.HrefRelation.MEMBER -> memberElements.add(response) + Response.HrefRelation.SELF -> rootElement = response + Response.HrefRelation.OTHER -> {} + else -> {} + } + } + + assertTrue(davResponse?.isSuccess() == true) + assertTrue(rootElement != null) + assertEquals(0, memberElements.size) + + val remoteFile = WebDavFileUtils().parseResponse(rootElement, nextcloudClient.filesDavUri) + + val date = davResponse?.get(CreationDate::class.java) + assertEquals( + oldRemoteFile.creationTimestamp, + (WebdavUtils.parseResponseDate(date?.creationDate)?.time ?: 0) / 1000 + ) + + assertTrue(oldRemoteFile.isFavorite) + val favorite = davResponse?.get(NCFavorite::class.java) + assertTrue(favorite?.isOcFavorite == true) + + assertEquals(oldRemoteFile.remotePath, remoteFile.remotePath) + assertEquals(oldRemoteFile.mimeType, remoteFile.mimeType) + assertEquals(oldRemoteFile.length, remoteFile.length) + assertEquals(oldRemoteFile.creationTimestamp, remoteFile.creationTimestamp) + // assertEquals(oldRemoteFile.modifiedTimestamp, remoteFile.modifiedTimestamp) + assertEquals(oldRemoteFile.uploadTimestamp, remoteFile.uploadTimestamp) + assertEquals(oldRemoteFile.etag, remoteFile.etag) + assertEquals(oldRemoteFile.permissions, remoteFile.permissions) + assertEquals(oldRemoteFile.remoteId, remoteFile.remoteId) + assertEquals(oldRemoteFile.size, remoteFile.size) + assertEquals(oldRemoteFile.isFavorite, remoteFile.isFavorite) + assertEquals(oldRemoteFile.isEncrypted, remoteFile.isEncrypted) + assertEquals(oldRemoteFile.mountType, remoteFile.mountType) + assertEquals(oldRemoteFile.ownerId, remoteFile.ownerId) + assertEquals(oldRemoteFile.ownerDisplayName, remoteFile.ownerDisplayName) + assertEquals(oldRemoteFile.unreadCommentsCount, remoteFile.unreadCommentsCount) + assertEquals(oldRemoteFile.isHasPreview, remoteFile.isHasPreview) + assertEquals(oldRemoteFile.note, remoteFile.note) + assertEquals(oldRemoteFile.sharees.size, remoteFile.sharees.size) + assertEquals(oldRemoteFile.richWorkspace, remoteFile.richWorkspace) + assertEquals(oldRemoteFile.isLocked, remoteFile.isLocked) + assertEquals(oldRemoteFile.lockType, remoteFile.lockType) + assertEquals(oldRemoteFile.lockOwner, remoteFile.lockOwner) + assertEquals(oldRemoteFile.lockOwnerDisplayName, remoteFile.lockOwnerDisplayName) + assertEquals(oldRemoteFile.lockTimestamp, remoteFile.lockTimestamp) + assertEquals(oldRemoteFile.lockOwnerEditor, remoteFile.lockOwnerEditor) + assertEquals(oldRemoteFile.lockTimeout, remoteFile.lockTimeout) + assertEquals(oldRemoteFile.lockToken, remoteFile.lockToken) + assertEquals(oldRemoteFile.localId, remoteFile.localId) + } + + @Test + fun search() { + val path = "/testFolder/" + + // create folder + assertTrue( + CreateFolderRemoteOperation( + path, + true + ).execute(client).isSuccess + ) + + // create file + val filePath = createFile("text") + val remotePath = "/test.md" + + assertTrue( + UploadFileRemoteOperation( + filePath, + remotePath, + "text/markdown", + "", + RANDOM_MTIME, + System.currentTimeMillis(), + true + ).execute(client).isSuccess + ) + + WebdavUtils.registerCustomFactories() + + var ror = SearchRemoteOperation( + "test", + SearchRemoteOperation.SearchType.FILE_SEARCH, + false, + OCCapability(23, 0, 0) + ).execute( + client + ) + + assertTrue(ror.isSuccess) + assertEquals(2, ror.resultData.size) + + val oldRemoteFile = ror.resultData[0] + assertEquals(path, oldRemoteFile.remotePath) + + ror = SearchRemoteOperation( + "test", + SearchRemoteOperation.SearchType.FILE_SEARCH, + false, + OCCapability(23, 0, 0) + ).execute( + nextcloudClient + ) + + assertTrue(ror.isSuccess) + assertEquals(2, ror.resultData.size) + + val remoteFile = ror.resultData[0] + assertEquals(path, remoteFile.remotePath) + + assertEquals(oldRemoteFile.remoteId, remoteFile.remoteId) + } + + @Test + fun propPatch() { + val path = "/testFolder/" + + // create folder + assertTrue(CreateFolderRemoteOperation(path, true).execute(client).isSuccess) + + // make it favorite + assertTrue( + ToggleFavoriteRemoteOperation(true, path).execute(nextcloudClient).isSuccess + ) + + val result = ReadFolderRemoteOperation(path).execute(client) + assertTrue(result.isSuccess) + val list = result.data as List + assertTrue(list[0].isFavorite) + } +} diff --git a/library/src/androidTest/java/com/owncloud/android/FileIT.java b/library/src/androidTest/java/com/owncloud/android/FileIT.java index 0aaf32e655..b4f8a5327f 100644 --- a/library/src/androidTest/java/com/owncloud/android/FileIT.java +++ b/library/src/androidTest/java/com/owncloud/android/FileIT.java @@ -26,6 +26,10 @@ */ package com.owncloud.android; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import android.net.Uri; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -43,10 +47,6 @@ import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - /** * Tests related to file operations */ @@ -60,6 +60,7 @@ public void testCreateFolderSuccess() { // verify folder assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); // remove folder assertTrue(new RemoveFileRemoteOperation(path).execute(client).isSuccess()); 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 8b71800226..a58ccaaadb 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 @@ -164,22 +164,43 @@ public void noFavorites() { @Test public void oneFavorite() { String path = "/testFolder/"; + String path2 = "/testFolder2/"; // create folder, make it favorite new CreateFolderRemoteOperation(path, true).execute(client); + new CreateFolderRemoteOperation(path2, true).execute(client); assertTrue(new ToggleFavoriteRemoteOperation(true, path).execute(client).isSuccess()); + assertTrue(new ToggleFavoriteRemoteOperation(true, path2).execute(nextcloudClient).isSuccess()); SearchRemoteOperation sut = new SearchRemoteOperation("", SearchRemoteOperation.SearchType.FAVORITE_SEARCH, false, capability); - RemoteOperationResult> result = sut.execute(client); + RemoteOperationResult> result = sut.execute(nextcloudClient); // test assertTrue(result.isSuccess()); - assertEquals(1, result.getResultData().size()); + assertEquals(2, result.getResultData().size()); + RemoteFile remoteFile = result.getResultData().get(0); assertEquals(path, remoteFile.getRemotePath()); + + RemoteFile remoteFile2 = result.getResultData().get(1); + assertEquals(path2, remoteFile2.getRemotePath()); + + // unfavorite + assertTrue(new ToggleFavoriteRemoteOperation(false, path).execute(client).isSuccess()); + assertTrue(new ToggleFavoriteRemoteOperation(false, path2).execute(nextcloudClient).isSuccess()); + + // test + sut = new SearchRemoteOperation("", + SearchRemoteOperation.SearchType.FAVORITE_SEARCH, + false, + capability); + result = sut.execute(nextcloudClient); + + assertTrue(result.isSuccess()); + assertEquals(0, result.getResultData().size()); } @Test diff --git a/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.java b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.java new file mode 100644 index 0000000000..0c154024bc --- /dev/null +++ b/library/src/main/java/com/nextcloud/common/NextcloudAuthenticator.java @@ -0,0 +1,64 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package com.nextcloud.common; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import okhttp3.Authenticator; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Route; + +public class NextcloudAuthenticator implements Authenticator { + private String credentials; + private String authenticatorType; + + public NextcloudAuthenticator(@NonNull String credentials, @NonNull String authenticatorType) { + this.credentials = credentials; + this.authenticatorType = authenticatorType; + } + + @Nullable + @Override + public Request authenticate(@Nullable Route route, @NonNull Response response) { + if (response.request().header(authenticatorType) != null) { + return null; + } + + Response countedResponse = response; + + int attemptsCount = 0; + + while ((countedResponse = countedResponse.priorResponse()) != null) { + attemptsCount++; + if (attemptsCount == 3) { + return null; + } + } + + return response.request().newBuilder() + .header(authenticatorType, credentials) + .build(); + } +} diff --git a/library/src/main/java/com/nextcloud/operations/SearchMethod.kt b/library/src/main/java/com/nextcloud/operations/SearchMethod.kt new file mode 100644 index 0000000000..6a3dec59be --- /dev/null +++ b/library/src/main/java/com/nextcloud/operations/SearchMethod.kt @@ -0,0 +1,25 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package com.nextcloud.operations + +class SearchMethod diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.java b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.java index 57c830c959..4c5f404c3e 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.java +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.java @@ -90,15 +90,22 @@ public class WebdavEntry { public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes"; public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; + public static final String DIR_TYPE = "DIR"; + private static final String IS_ENCRYPTED = "1"; private static final int CODE_PROP_NOT_FOUND = 404; - @Getter private String name; - @Getter private String path; - @Getter private String uri; - @Getter private String contentType; - @Getter private String eTag; + @Getter + private String name; + @Getter + private String path; + @Getter + private String uri; + @Getter + private String contentType; + @Getter + private String eTag; @Getter private String permissions; @Getter private String remoteId; @Getter private String trashbinOriginalLocation; @@ -195,10 +202,10 @@ public WebdavEntry(MultiStatusResponse ms, String splitElement) { if (prop!= null) { Object value = prop.getValue(); if (value != null) { - contentType = "DIR"; // a specific attribute would be better, - // but this is enough; - // unless while we have no reason to distinguish - // MIME types for folders + 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 } } @@ -525,7 +532,7 @@ public String decodedPath() { } public boolean isDirectory() { - return "DIR".equals(contentType); + return DIR_TYPE.equals(contentType); } private void resetData() { 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 95860b49a2..e09147dcd4 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 @@ -1,23 +1,23 @@ /* ownCloud Android Library is available under MIT license * Copyright (C) 2015 ownCloud Inc. * Copyright (C) 2012 Bartek Przybylski - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * @@ -29,6 +29,17 @@ import androidx.annotation.Nullable; +import com.nextcloud.talk.components.filebrowser.models.properties.OCId; +import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerDisplayName; +import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerId; +import com.nextcloud.talk.components.filebrowser.models.properties.OCSize; +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.NCMountType; +import com.owncloud.android.lib.resources.files.webdav.NCPermissions; +import com.owncloud.android.lib.resources.files.webdav.NCRichWorkspace; +import com.owncloud.android.lib.resources.files.webdav.NCSharee; + import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpMethod; import org.apache.jackrabbit.webdav.property.DavPropertyName; @@ -37,9 +48,22 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.Locale; +import at.bitfire.dav4jvm.Property; +import at.bitfire.dav4jvm.PropertyFactory; +import at.bitfire.dav4jvm.PropertyRegistry; +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.GetLastModified; +import at.bitfire.dav4jvm.property.ResourceType; + public class WebdavUtils { private static final SimpleDateFormat DATETIME_FORMATS[] = { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US), @@ -71,23 +95,24 @@ Date parseResponseDate(String date) { } /** - * Encodes a path according to URI RFC 2396. - * + * 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 "/" + * + * @param remoteFilePath Path + * @return Encoded path according to RFC 2396, always starting with "/" */ public static String encodePath(String remoteFilePath) { String encodedPath = Uri.encode(remoteFilePath, "/"); - if (!encodedPath.startsWith("/")) + if (!encodedPath.startsWith("/")) { encodedPath = "/" + encodedPath; + } return encodedPath; } /** - * Builds a DavPropertyNameSet with all prop - * For using instead of DavConstants.PROPFIND_ALL_PROP + * Builds a DavPropertyNameSet with all prop For using instead of DavConstants.PROPFIND_ALL_PROP + * * @return */ public static DavPropertyNameSet getAllPropSet() { @@ -128,14 +153,59 @@ public static DavPropertyNameSet getAllPropSet() { return propSet; } + public static Property.Name[] getAllPropertiesList() { + List list = new ArrayList<>(); + + list.add(CreationDate.NAME); + list.add(NCFavorite.NAME); + list.add(NCEtag.NAME); + list.add(GetLastModified.NAME); + list.add(GetContentType.NAME); + list.add(ResourceType.NAME); + list.add(NCPermissions.NAME); + list.add(OCId.NAME); + list.add(OCSize.NAME); + list.add(NCMountType.NAME); + list.add(OCOwnerId.NAME); + list.add(OCOwnerDisplayName.NAME); + list.add(NCRichWorkspace.NAME); + + list.add(DisplayName.NAME); + list.add(GetContentType.NAME); + list.add(GetContentLength.NAME); + list.add(GetContentType.NAME); + list.add(GetContentLength.NAME); + list.add(GetLastModified.NAME); + list.add(CreationDate.NAME); + list.add(GetETag.NAME); + list.add(ResourceType.NAME); + list.add(NCSharee.NAME); + +// list.add(NCPermission.NAME); +// list.add(OCId.NAME); +// list.add(OCSize.NAME); +// list.add(OCFavorite.NAME); +// list.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_ID)); +// list.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_DISPLAY_NAME)); +// list.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_UNREAD_COMMENTS)); +// +// list.add(NCEncrypted.NAME); +// list.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_MOUNT_TYPE)); +// list.add(NCPreview.NAME); +// list.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_NOTE)); + + return list.toArray(new Property.Name[0]); + } + /** * Builds a DavPropertyNameSet with properties for files + * * @return */ public static DavPropertyNameSet getFilePropSet() { Namespace ocNamespace = Namespace.getNamespace(WebdavEntry.NAMESPACE_OC); Namespace ncNamespace = Namespace.getNamespace(WebdavEntry.NAMESPACE_NC); - + DavPropertyNameSet propSet = new DavPropertyNameSet(); propSet.add(DavPropertyName.DISPLAYNAME); propSet.add(DavPropertyName.GETCONTENTTYPE); @@ -167,6 +237,7 @@ public static DavPropertyNameSet getFilePropSet() { /** * Builds a DavPropertyNameSet with properties for trashbin + * * @return */ public static DavPropertyNameSet getTrashbinPropSet() { @@ -185,6 +256,7 @@ public static DavPropertyNameSet getTrashbinPropSet() { /** * Builds a DavPropertyNameSet with properties for versions + * * @return */ public static DavPropertyNameSet getFileVersionPropSet() { @@ -212,7 +284,6 @@ public static DavPropertyNameSet getChunksPropSet() { } /** - * * @param rawEtag * @return */ @@ -231,7 +302,6 @@ public static String parseEtag(String rawEtag) { /** - * * @param method * @return */ @@ -253,4 +323,19 @@ public static String getEtagFromResponse(HttpMethod method) { return result; } + public static void registerCustomFactories() { + List list = new ArrayList<>(); + list.add(new NCFavorite.Factory()); + list.add(new NCEtag.Factory()); + list.add(new NCPermissions.Factory()); + list.add(new OCId.Factory()); + list.add(new OCSize.Factory()); + list.add(new NCMountType.Factory()); + list.add(new OCOwnerId.Factory()); + list.add(new OCOwnerDisplayName.Factory()); + list.add(new NCRichWorkspace.Factory()); + list.add(new NCSharee.Factory()); + + PropertyRegistry.INSTANCE.register(list); + } } diff --git a/library/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperation.java index 1a04b80be8..e75006217a 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperation.java @@ -448,11 +448,14 @@ public void run() { /** * Returns the current client instance to access the remote server. - * - * @return Current client instance to access the remote server. + * + * @return Current client instance to access the remote server. */ public final OwnCloudClient getClient() { return mClient; } + public final NextcloudClient getClientNew() { + return clientNew; + } } diff --git a/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils.java b/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils.java index 8097a8d844..b6c3f90b0e 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils.java +++ b/library/src/main/java/com/owncloud/android/lib/common/utils/WebDavFileUtils.java @@ -27,14 +27,32 @@ package com.owncloud.android.lib.common.utils; -import com.owncloud.android.lib.common.OwnCloudClient; +import android.net.Uri; + +import com.nextcloud.talk.components.filebrowser.models.properties.OCId; +import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerDisplayName; +import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerId; +import com.nextcloud.talk.components.filebrowser.models.properties.OCSize; 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.NCEtag; +import com.owncloud.android.lib.resources.files.webdav.NCFavorite; +import com.owncloud.android.lib.resources.files.webdav.NCMountType; +import com.owncloud.android.lib.resources.files.webdav.NCPermissions; +import com.owncloud.android.lib.resources.files.webdav.NCRichWorkspace; +import com.owncloud.android.lib.resources.files.webdav.NCSharee; import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import java.util.ArrayList; +import java.util.List; + +import at.bitfire.dav4jvm.Property; +import at.bitfire.dav4jvm.Response; +import at.bitfire.dav4jvm.property.GetContentType; +import at.bitfire.dav4jvm.property.GetLastModified; +import at.bitfire.dav4jvm.property.ResourceType; /** * WebDav helper. @@ -44,14 +62,13 @@ public class WebDavFileUtils { /** * 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 client Client instance to the remote server where the data were - * retrieved. + * @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 */ public ArrayList readData(MultiStatus remoteData, - OwnCloudClient client, + Uri filesDavUri, boolean isReadFolderOperation, boolean isSearchOperation) { ArrayList mFolderAndFiles = new ArrayList<>(); @@ -61,7 +78,7 @@ public ArrayList readData(MultiStatus remoteData, if (isReadFolderOperation) { we = new WebdavEntry(remoteData.getResponses()[0], - client.getFilesDavUri().getEncodedPath()); + filesDavUri.getEncodedPath()); mFolderAndFiles.add(new RemoteFile(we)); } else { start = 0; @@ -72,11 +89,86 @@ public ArrayList readData(MultiStatus remoteData, MultiStatusResponse[] responses = remoteData.getResponses(); for (int i = start; i < responses.length; i++) { /// new OCFile instance with the data from the server - we = new WebdavEntry(responses[i], client.getFilesDavUri().getEncodedPath()); + we = new WebdavEntry(responses[i], filesDavUri.getEncodedPath()); remoteFile = new RemoteFile(we); mFolderAndFiles.add(remoteFile); } return mFolderAndFiles; } + + public ArrayList readData(List responses, Uri filesDavUri) { + ArrayList list = new ArrayList<>(); + + for (Response response : responses) { + list.add(parseResponse(response, filesDavUri)); + } + + return list; + } + + public RemoteFile parseResponse(Response response, Uri filesDavUri) { + RemoteFile remoteFile = new RemoteFile(); + String path = response.getHref().toString().split(filesDavUri.getEncodedPath(), 2)[1].replace("//", "/"); + + for (Property property : response.getProperties()) { + if (property instanceof NCEtag) { + remoteFile.setEtag(((NCEtag) property).getEtag()); + } + + if (property instanceof NCFavorite) { + remoteFile.setFavorite(((NCFavorite) property).isOcFavorite()); + } + + if (property instanceof GetLastModified) { + remoteFile.setModifiedTimestamp(((GetLastModified) property).getLastModified()); + } + + if (property instanceof GetContentType) { + remoteFile.setMimeType(((GetContentType) property).getType().toString()); + } + + if (property instanceof ResourceType) { + if (((ResourceType) property).getTypes().contains(ResourceType.Companion.getCOLLECTION())) { + remoteFile.setMimeType(WebdavEntry.DIR_TYPE); + } + } + + if (property instanceof NCPermissions) { + remoteFile.setPermissions(((NCPermissions) property).getPermissions()); + } + + if (property instanceof OCId) { + remoteFile.setRemoteId(((OCId) property).getOcId()); + } + + if (property instanceof OCSize) { + remoteFile.setSize(((OCSize) property).getOcSize()); + } + + if (property instanceof NCMountType) { + remoteFile.setMountType(((NCMountType) property).getType()); + } + + if (property instanceof OCOwnerId) { + remoteFile.setOwnerId(((OCOwnerId) property).getOwnerId()); + } + + if (property instanceof OCOwnerDisplayName) { + remoteFile.setOwnerDisplayName(((OCOwnerDisplayName) property).getString()); + } + + if (property instanceof NCRichWorkspace) { + remoteFile.setRichWorkspace(((NCRichWorkspace) property).getRichWorkspace()); + } + + if (property instanceof NCSharee) { + remoteFile.setSharees(((NCSharee) property).getSharees()); + } + } + + remoteFile.setRemotePath(path); + + return remoteFile; + } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/NcSearchMethod.java b/library/src/main/java/com/owncloud/android/lib/resources/files/NcSearchMethod.java index d49faa44c1..81c4295a46 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/NcSearchMethod.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/NcSearchMethod.java @@ -26,6 +26,10 @@ */ package com.owncloud.android.lib.resources.files; +import static com.owncloud.android.lib.common.network.WebdavEntry.EXTENDED_PROPERTY_IS_ENCRYPTED; +import static com.owncloud.android.lib.common.network.WebdavEntry.NAMESPACE_NC; +import static com.owncloud.android.lib.common.network.WebdavEntry.NAMESPACE_OC; + import com.owncloud.android.lib.resources.status.NextcloudVersion; import com.owncloud.android.lib.resources.status.OCCapability; @@ -45,10 +49,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import static com.owncloud.android.lib.common.network.WebdavEntry.EXTENDED_PROPERTY_IS_ENCRYPTED; -import static com.owncloud.android.lib.common.network.WebdavEntry.NAMESPACE_NC; -import static com.owncloud.android.lib.common.network.WebdavEntry.NAMESPACE_OC; - public class NcSearchMethod extends org.apache.jackrabbit.webdav.client.methods.SearchMethod { private static final String HEADER_CONTENT_TYPE_VALUE = "text/xml"; private static final String DAV_NAMESPACE = "DAV:"; @@ -87,6 +87,10 @@ public NcSearchMethod(String uri, setRequestBody(createQuery(searchInfo.getQuery())); } + public Document getDocumentQuery(SearchInfo searchInfo) { + return createQuery(searchInfo.getQuery()); + } + private Document createQuery(String searchQuery) { String internalSearchString = searchQuery; diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/SearchRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/files/SearchRemoteOperation.java index 052f25ba7b..bc92c380e9 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/SearchRemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/SearchRemoteOperation.java @@ -27,6 +27,8 @@ package com.owncloud.android.lib.resources.files; +import com.nextcloud.common.NextcloudAuthenticator; +import com.nextcloud.common.NextcloudClient; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -39,10 +41,23 @@ import org.apache.jackrabbit.webdav.client.methods.OptionsMethod; import org.apache.jackrabbit.webdav.search.SearchInfo; import org.apache.jackrabbit.webdav.xml.Namespace; +import org.w3c.dom.Document; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import at.bitfire.dav4jvm.DavResource; +import at.bitfire.dav4jvm.Response; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; + /** * Remote operation performing the search in the Nextcloud server. */ @@ -88,15 +103,15 @@ public SearchRemoteOperation(String query, public void setLimit(int limit) { this.limit = limit; } - + public void setTimestamp(long timestamp) { this.timestamp = timestamp; } - + public void setStartDate(Long startDate) { this.startDate = startDate; } - + public void setEndDate(Long endDate) { this.endDate = endDate; } @@ -111,53 +126,44 @@ protected RemoteOperationResult> run(OwnCloudClient client) { optionsMethod = new OptionsMethod(webDavUrl); try { - int optionsStatus = client.executeMethod(optionsMethod); - boolean isSearchSupported = optionsMethod.isAllowed("SEARCH"); - - if (isSearchSupported) { - searchMethod = new NcSearchMethod(webDavUrl, - new SearchInfo("NC", - Namespace.XMLNS_NAMESPACE, - searchQuery), - searchType, - getClient().getUserIdPlain(), - timestamp, - limit, - filterOutFiles, - capability, - startDate, - endDate); - - int status = client.executeMethod(searchMethod); - - // check and process response - boolean isSuccess = (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK); - - if (isSuccess) { - // get data from remote folder - MultiStatus dataInServer = searchMethod.getResponseBodyAsMultiStatus(); - WebDavFileUtils webDavFileUtils = new WebDavFileUtils(); - ArrayList mFolderAndFiles = webDavFileUtils.readData(dataInServer, - client, - false, - true); - - // Result of the operation - result = new RemoteOperationResult<>(true, status, searchMethod.getResponseHeaders()); - // Add data to the result - if (result.isSuccess()) { - result.setResultData(mFolderAndFiles); - } - } else { - // synchronization failed - client.exhaustResponse(searchMethod.getResponseBodyAsStream()); - result = new RemoteOperationResult<>(false, status, searchMethod.getResponseHeaders()); + searchMethod = new NcSearchMethod(webDavUrl, + new SearchInfo("NC", + Namespace.XMLNS_NAMESPACE, + searchQuery), + searchType, + getClient().getUserIdPlain(), + timestamp, + limit, + filterOutFiles, + capability, + startDate, + endDate); + + int status = client.executeMethod(searchMethod); + + // check and process response + boolean isSuccess = (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK); + + if (isSuccess) { + // get data from remote folder + MultiStatus dataInServer = searchMethod.getResponseBodyAsMultiStatus(); + WebDavFileUtils webDavFileUtils = new WebDavFileUtils(); + ArrayList mFolderAndFiles = webDavFileUtils.readData(dataInServer, + client.getFilesDavUri(), + false, + true); + + // Result of the operation + result = new RemoteOperationResult<>(true, status, searchMethod.getResponseHeaders()); + // Add data to the result + if (result.isSuccess()) { + result.setResultData(mFolderAndFiles); } } else { - client.exhaustResponse(optionsMethod.getResponseBodyAsStream()); - result = new RemoteOperationResult<>(false, optionsStatus, optionsMethod.getResponseHeaders()); + // synchronization failed + client.exhaustResponse(searchMethod.getResponseBodyAsStream()); + result = new RemoteOperationResult<>(false, status, searchMethod.getResponseHeaders()); } - } catch (Exception e) { result = new RemoteOperationResult<>(e); } finally { @@ -169,5 +175,82 @@ protected RemoteOperationResult> run(OwnCloudClient client) { } return result; } + + @Override + public RemoteOperationResult run(NextcloudClient client) { + RemoteOperationResult> result; + NcSearchMethod searchMethod = null; + + String webDavUrl = client.getDavUri().toString(); + + SearchInfo searchInfo = new SearchInfo("NC", + Namespace.XMLNS_NAMESPACE, + searchQuery); + + try { + searchMethod = new NcSearchMethod(webDavUrl, + searchInfo, + searchType, + getClientNew().getUserIdPlain(), + timestamp, + limit, + filterOutFiles, + capability, + startDate, + endDate); + + // disable redirect + OkHttpClient disabledRedirectClient = client.getClient() + .newBuilder() + .followRedirects(false) + .authenticator(new NextcloudAuthenticator(client.getCredentials(), "Authorization")) + .build(); + + Document searchDocument = searchMethod.getDocumentQuery(searchInfo); + String searchString = transformDocumentToString(searchDocument); + + ArrayList responses = new ArrayList<>(); + + new DavResource( + disabledRedirectClient, + HttpUrl.get(client.getDavUri().toString())) + .search(searchString, (response, hrefRelation) -> { + responses.add(response); + }); + + // get data from remote folder + WebDavFileUtils webDavFileUtils = new WebDavFileUtils(); + + ArrayList list = new ArrayList<>(); + for (Response response : responses) { + list.add(webDavFileUtils.parseResponse(response, client.getFilesDavUri())); + } + + // Result of the operation + result = new RemoteOperationResult<>( + true, + HttpStatus.SC_OK, + searchMethod.getResponseHeaders()); + // Add data to the result + if (result.isSuccess()) { + result.setResultData(list); + } + } catch (Exception e) { + result = new RemoteOperationResult<>(e); + } finally { + if (searchMethod != null) { + searchMethod.releaseConnection(); // let the connection available for other methods + } + } + return result; + } + + public String transformDocumentToString(Document document) throws TransformerException { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer trans = tf.newTransformer(); + StringWriter sw = new StringWriter(); + trans.transform(new DOMSource(document), new StreamResult(sw)); + return sw.toString(); + } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ToggleFavoriteRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/files/ToggleFavoriteRemoteOperation.java index 10261d6c8b..8e3938b7ac 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/ToggleFavoriteRemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/ToggleFavoriteRemoteOperation.java @@ -29,10 +29,13 @@ import android.net.Uri; +import com.nextcloud.common.NextcloudAuthenticator; +import com.nextcloud.common.NextcloudClient; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.network.WebdavEntry; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.webdav.NCFavorite; import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod; @@ -42,6 +45,15 @@ import org.apache.jackrabbit.webdav.xml.Namespace; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import at.bitfire.dav4jvm.DavResource; +import at.bitfire.dav4jvm.Property; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; /** * Favorite or unfavorite a file. @@ -89,7 +101,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { } } catch (IOException e) { result = new RemoteOperationResult(e); - } finally { + } finally { if (propPatchMethod != null) { propPatchMethod.releaseConnection(); // let the connection available for other methods } @@ -97,4 +109,41 @@ protected RemoteOperationResult run(OwnCloudClient client) { return result; } + + @Override + public RemoteOperationResult run(NextcloudClient client) { + RemoteOperationResult result; + + List removeProperties = new ArrayList<>(); + Map newProperties = new HashMap<>(); + + // disable redirect + OkHttpClient disabledRedirectClient = client.getClient() + .newBuilder() + .followRedirects(false) + .authenticator(new NextcloudAuthenticator(client.getCredentials(), "Authorization")) + .build(); + + if (makeItFavorited) { + newProperties.put(NCFavorite.NAME, "1"); + } else { + removeProperties.add(NCFavorite.NAME); + } + + String webDavUrl = client.getDavUri().toString(); + String encodedPath = (client.getUserId() + Uri.encode(filePath)).replace("%2F", "/"); + String fullFilePath = webDavUrl + "/files/" + encodedPath; + + boolean resultCode = false; + + new DavResource(disabledRedirectClient, + HttpUrl.get(fullFilePath)) + .proppatch(newProperties, removeProperties, (response, hrefRelation) -> { + //resultCode = response.isSuccess(); + }); + + result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK); + + return result; + } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.java b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.java index 8254c71bfb..ed459eaa40 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.java @@ -1,22 +1,22 @@ /* ownCloud Android Library is available under MIT license * Copyright (C) 2015 ownCloud Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * @@ -32,18 +32,16 @@ import com.owncloud.android.lib.resources.shares.ShareeUser; import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import lombok.Getter; -import lombok.Setter; /** * Contains the data of a Remote File from a WebDavEntry. * * @author masensio */ -@Getter -@Setter public class RemoteFile implements Parcelable, Serializable { /** * Generated - should be refreshed every time the class changes!! @@ -85,7 +83,7 @@ public RemoteFile() { /** * Create new {@link RemoteFile} with given path. - * + *

* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'. * * @param path The remote path of the file. @@ -250,4 +248,242 @@ public String getLocalId() { return remoteId.substring(0, 8).replaceAll("^0*", ""); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RemoteFile that = (RemoteFile) o; + return length == that.length && creationTimestamp == that.creationTimestamp && modifiedTimestamp == that.modifiedTimestamp && uploadTimestamp == that.uploadTimestamp && size == that.size && favorite == that.favorite && encrypted == that.encrypted && unreadCommentsCount == that.unreadCommentsCount && hasPreview == that.hasPreview && isLocked == that.isLocked && lockTimestamp == that.lockTimestamp && lockTimeout == that.lockTimeout && Objects.equals(remotePath, that.remotePath) && Objects.equals(mimeType, that.mimeType) && Objects.equals(etag, that.etag) && Objects.equals(permissions, that.permissions) && Objects.equals(remoteId, that.remoteId) && mountType == that.mountType && Objects.equals(ownerId, that.ownerId) && Objects.equals(ownerDisplayName, that.ownerDisplayName) && Objects.equals(note, that.note) && Arrays.equals(sharees, that.sharees) && Objects.equals(richWorkspace, that.richWorkspace) && lockType == that.lockType && Objects.equals(lockOwner, that.lockOwner) && Objects.equals(lockOwnerDisplayName, that.lockOwnerDisplayName) && Objects.equals(lockOwnerEditor, that.lockOwnerEditor) && Objects.equals(lockToken, that.lockToken); + } + + @Override + public int hashCode() { + int result = Objects.hash(remotePath, mimeType, length, creationTimestamp, modifiedTimestamp, uploadTimestamp, etag, permissions, remoteId, size, favorite, encrypted, mountType, ownerId, ownerDisplayName, unreadCommentsCount, hasPreview, note, richWorkspace, isLocked, lockType, lockOwner, lockOwnerDisplayName, lockTimestamp, lockOwnerEditor, lockTimeout, lockToken); + result = 31 * result + Arrays.hashCode(sharees); + return result; + } + + public String getRemotePath() { + return remotePath; + } + + public void setRemotePath(String remotePath) { + this.remotePath = remotePath; + } + + public String getMimeType() { + return mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public long getLength() { + return length; + } + + public void setLength(long length) { + this.length = length; + } + + public long getCreationTimestamp() { + return creationTimestamp; + } + + public void setCreationTimestamp(long creationTimestamp) { + this.creationTimestamp = creationTimestamp; + } + + public long getModifiedTimestamp() { + return modifiedTimestamp; + } + + public void setModifiedTimestamp(long modifiedTimestamp) { + this.modifiedTimestamp = modifiedTimestamp; + } + + public long getUploadTimestamp() { + return uploadTimestamp; + } + + public void setUploadTimestamp(long uploadTimestamp) { + this.uploadTimestamp = uploadTimestamp; + } + + public String getEtag() { + return etag; + } + + public void setEtag(String etag) { + this.etag = etag; + } + + public String getPermissions() { + return permissions; + } + + public void setPermissions(String permissions) { + this.permissions = permissions; + } + + public String getRemoteId() { + return remoteId; + } + + public void setRemoteId(String remoteId) { + this.remoteId = remoteId; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public boolean isFavorite() { + return favorite; + } + + public void setFavorite(boolean favorite) { + this.favorite = favorite; + } + + public boolean isEncrypted() { + return encrypted; + } + + public void setEncrypted(boolean encrypted) { + this.encrypted = encrypted; + } + + public WebdavEntry.MountType getMountType() { + return mountType; + } + + public void setMountType(WebdavEntry.MountType mountType) { + this.mountType = mountType; + } + + public String getOwnerId() { + return ownerId; + } + + public void setOwnerId(String ownerId) { + this.ownerId = ownerId; + } + + public String getOwnerDisplayName() { + return ownerDisplayName; + } + + public void setOwnerDisplayName(String ownerDisplayName) { + this.ownerDisplayName = ownerDisplayName; + } + + public int getUnreadCommentsCount() { + return unreadCommentsCount; + } + + public void setUnreadCommentsCount(int unreadCommentsCount) { + this.unreadCommentsCount = unreadCommentsCount; + } + + public boolean isHasPreview() { + return hasPreview; + } + + public void setHasPreview(boolean hasPreview) { + this.hasPreview = hasPreview; + } + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + + public ShareeUser[] getSharees() { + return sharees; + } + + public void setSharees(ShareeUser[] sharees) { + this.sharees = sharees; + } + + public String getRichWorkspace() { + return richWorkspace; + } + + public void setRichWorkspace(String richWorkspace) { + this.richWorkspace = richWorkspace; + } + + public boolean isLocked() { + return isLocked; + } + + public void setLocked(boolean locked) { + isLocked = locked; + } + + public FileLockType getLockType() { + return lockType; + } + + public void setLockType(FileLockType lockType) { + this.lockType = lockType; + } + + public String getLockOwner() { + return lockOwner; + } + + public void setLockOwner(String lockOwner) { + this.lockOwner = lockOwner; + } + + public String getLockOwnerDisplayName() { + return lockOwnerDisplayName; + } + + public void setLockOwnerDisplayName(String lockOwnerDisplayName) { + this.lockOwnerDisplayName = lockOwnerDisplayName; + } + + public long getLockTimestamp() { + return lockTimestamp; + } + + public void setLockTimestamp(long lockTimestamp) { + this.lockTimestamp = lockTimestamp; + } + + public String getLockOwnerEditor() { + return lockOwnerEditor; + } + + public void setLockOwnerEditor(String lockOwnerEditor) { + this.lockOwnerEditor = lockOwnerEditor; + } + + public long getLockTimeout() { + return lockTimeout; + } + + public void setLockTimeout(long lockTimeout) { + this.lockTimeout = lockTimeout; + } + + public String getLockToken() { + return lockToken; + } + + public void setLockToken(String lockToken) { + this.lockToken = lockToken; + } } 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 0000000000..af73fbd145 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEncrypted.kt @@ -0,0 +1,40 @@ +package com.owncloud.android.lib.resources.files.webdav + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCEncrypted private constructor(var isNcEncrypted: Boolean) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = XmlUtils.readText(parser) + if (!TextUtils.isEmpty(text)) { + 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) + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_NC, WebdavEntry.EXTENDED_PROPERTY_IS_ENCRYPTED) + } +} 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 0000000000..ba81292cd8 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt @@ -0,0 +1,50 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +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.WebdavUtils +import org.xmlpull.v1.XmlPullParser + +class NCEtag internal constructor(var etag: String) : Property { + + companion object { + @JvmField + val NAME = Property.Name(XmlUtils.NS_WEBDAV, "getetag") + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCEtag? { + // + XmlUtils.readText(parser)?.let { rawEtag -> + return NCEtag(WebdavUtils.parseEtag(rawEtag)) + } + return 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 new file mode 100644 index 0000000000..cb58625a8c --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCFavorite.kt @@ -0,0 +1,62 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCFavorite internal constructor(var isOcFavorite: Boolean) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + 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) + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_OC, WebdavEntry.EXTENDED_PROPERTY_FAVORITE) + } +} 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 0000000000..b075431774 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCMountType.kt @@ -0,0 +1,54 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser + +class NCMountType internal constructor(var type: WebdavEntry.MountType) : Property { + + companion object { + @JvmField + val NAME = Property.Name(WebdavEntry.NAMESPACE_NC, WebdavEntry.EXTENDED_PROPERTY_MOUNT_TYPE) + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCMountType { + // (#PCDATA) > + val r = XmlUtils.readText(parser)?.let { type -> + when (type) { + "external" -> WebdavEntry.MountType.EXTERNAL + "group" -> WebdavEntry.MountType.GROUP + else -> WebdavEntry.MountType.INTERNAL + } + } ?: WebdavEntry.MountType.INTERNAL + return NCMountType(r) + } + } +} 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 0000000000..c6a0493a5f --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPermissions.kt @@ -0,0 +1,47 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser + +class NCPermissions internal constructor(var permissions: String) : Property { + + companion object { + @JvmField + val NAME = + Property.Name(WebdavEntry.NAMESPACE_OC, WebdavEntry.EXTENDED_PROPERTY_NAME_PERMISSIONS) + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser) = + // + NCPermissions(XmlUtils.readText(parser) ?: "") + } +} 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 0000000000..c20d77f06f --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCPreview.kt @@ -0,0 +1,62 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.lib.resources.files.webdav + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class NCPreview private constructor(var isNcPreview: Boolean) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + return NCPreview(java.lang.Boolean.parseBoolean(text)) + } + } 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) + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_NC, WebdavEntry.EXTENDED_PROPERTY_HAS_PREVIEW) + } +} 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 0000000000..c335a4220c --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCRichWorkspace.kt @@ -0,0 +1,52 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser + +class NCRichWorkspace internal constructor(var richWorkspace: String) : Property { + + companion object { + @JvmField + val NAME = + Property.Name(WebdavEntry.NAMESPACE_NC, WebdavEntry.EXTENDED_PROPERTY_RICH_WORKSPACE) + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCRichWorkspace? { + // NC rich-workspace property + // can be null if rich-workspace is disabled for this user + XmlUtils.readText(parser)?.let { string -> + return NCRichWorkspace(string) + } + return NCRichWorkspace("") + } + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharee.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharee.kt new file mode 100644 index 0000000000..56c5961ccb --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCSharee.kt @@ -0,0 +1,121 @@ +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +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 at.bitfire.dav4jvm.XmlUtils.readText +import com.owncloud.android.lib.common.network.WebdavEntry +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 NCSharee internal constructor(var sharees: Array) : Property { + + companion object { + @JvmField + val NAME = + Property.Name(WebdavEntry.NAMESPACE_NC, WebdavEntry.EXTENDED_PROPERTY_SHAREES) + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): NCSharee { + // NC sharees property + readArrayNode(parser).let { sharees -> + return NCSharee(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) { + list.add(readNCSharee(parser)) + } + + eventType = parser.next() + } + + return list + } + + private fun readNCSharee(parser: XmlPullParser): ShareeUser { + val depth = parser.depth + var eventType = parser.eventType + + val shareeUser = ShareeUser(null, null, null) + + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType != XmlPullParser.TEXT) { + when (parser.propertyName().toString()) { + "http://nextcloud.org/ns:id" -> { + shareeUser.userId = readText(parser) + } + "http://nextcloud.org/ns:display-name" -> { + shareeUser.displayName = readText(parser) + } + "http://nextcloud.org/ns:type" -> { + shareeUser.shareType = + ShareType.fromValue(readText(parser)?.toInt() ?: 0) + } + } + } + + eventType = parser.next() + } + + return shareeUser + } + } +} 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 0000000000..a1d2535b7b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCId.kt @@ -0,0 +1,62 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.components.filebrowser.models.properties + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCId private constructor(var ocId: String?) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + 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("") + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_OC, WebdavEntry.EXTENDED_PROPERTY_NAME_REMOTE_ID) + } +} 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 0000000000..9551c68578 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerDisplayName.kt @@ -0,0 +1,64 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.components.filebrowser.models.properties + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCOwnerDisplayName private constructor(var string: String?) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + 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("") + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = Property.Name( + WebdavEntry.NAMESPACE_OC, + WebdavEntry.EXTENDED_PROPERTY_OWNER_DISPLAY_NAME + ) + } +} 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 0000000000..32df45b214 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCOwnerId.kt @@ -0,0 +1,62 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.components.filebrowser.models.properties + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCOwnerId private constructor(var ownerId: String?) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + return OCOwnerId(text) + } + } catch (e: IOException) { + Log.e("OCId", "failed to create property", e) + } catch (e: XmlPullParserException) { + Log.e("OCId", "failed to create property", e) + } + return OCOwnerId("") + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_OC, WebdavEntry.EXTENDED_PROPERTY_OWNER_ID) + } +} 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 0000000000..7f41c39b3b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/OCSize.kt @@ -0,0 +1,62 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.components.filebrowser.models.properties + +import android.text.TextUtils +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.WebdavEntry +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import java.io.IOException + +class OCSize private constructor(var ocSize: Long) : Property { + + class Factory : PropertyFactory { + override fun create(parser: XmlPullParser): Property { + try { + val text = readText(parser) + if (!TextUtils.isEmpty(text)) { + 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(-1) + } + + override fun getName(): Property.Name { + return NAME + } + } + + companion object { + @JvmField + val NAME: Property.Name = + Property.Name(WebdavEntry.NAMESPACE_OC, WebdavEntry.EXTENDED_PROPERTY_NAME_SIZE) + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/shares/ShareeUser.kt b/library/src/main/java/com/owncloud/android/lib/resources/shares/ShareeUser.kt index 3283751016..3302c156e8 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/shares/ShareeUser.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/shares/ShareeUser.kt @@ -30,4 +30,5 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize -data class ShareeUser(val userId: String?, val displayName: String?, val shareType: ShareType?) : Parcelable +data class ShareeUser(var userId: String?, var displayName: String?, var shareType: ShareType?) : + Parcelable diff --git a/library/src/main/java/com/owncloud/android/lib/resources/status/OCCapability.kt b/library/src/main/java/com/owncloud/android/lib/resources/status/OCCapability.kt index 9ae4e729b7..93fc1ad380 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/status/OCCapability.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/status/OCCapability.kt @@ -27,14 +27,15 @@ package com.owncloud.android.lib.resources.status /** * Contains data of the Capabilities for an account, from the Capabilities API */ -class OCCapability { +class OCCapability( + var versionMayor: Int = 0, + var versionMinor: Int = 0, + var versionMicro: Int = 0 +) { var id: Long = 0 var accountName: String? = "" // Server version - var versionMayor = 0 - var versionMinor = 0 - var versionMicro = 0 var versionString: String? = "" var versionEdition: String? = null