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 40032d48c0..4c1e02af4b 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -50,7 +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 'com.github.bitfireAT:dav4jvm:2.1.4' + // 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 352761a620..1857c21e34 100644 --- a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -112,6 +112,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/Dav4JVMtest.kt b/library/src/androidTest/java/com/owncloud/android/Dav4JVMtest.kt new file mode 100644 index 0000000000..a64b10472b --- /dev/null +++ b/library/src/androidTest/java/com/owncloud/android/Dav4JVMtest.kt @@ -0,0 +1,260 @@ +/* + * 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.PropertyRegistry +import at.bitfire.dav4jvm.Response +import at.bitfire.dav4jvm.property.CreationDate +import at.bitfire.dav4jvm.property.GetContentType +import at.bitfire.dav4jvm.property.GetLastModified +import at.bitfire.dav4jvm.property.ResourceType +import com.nextcloud.common.NextcloudAuthenticator +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.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.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.Permissions +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 + +class Dav4JVMtest : 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) + + // 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 + registerProperties() + + DavResource( + client, + httpUrl + ) + + DavResource( + client, + httpUrl + ).propfind( + DavConstants.DEPTH_1, + CreationDate.NAME, + NCFavorite.NAME, + NCEtag.NAME, + GetLastModified.NAME, + GetContentType.NAME, + ResourceType.NAME, + Permissions.NAME, + OCId.NAME, + OCSize.NAME, + NCMountType.NAME, + OCOwnerId.NAME, + OCOwnerDisplayName.NAME + ) { 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, remoteFile.sharees) + 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) + + // assertEquals(oldRemoteFile, remoteFile) + } + + @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 + ) + + registerProperties() + + 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() { + assertTrue(false) + } + + private fun registerProperties() { + val list = listOf( + NCFavorite.Factory(), + NCEtag.Factory(), + Permissions.Factory(), + OCId.Factory(), + OCSize.Factory(), + NCMountType.Factory(), + OCOwnerId.Factory(), + OCOwnerDisplayName.Factory() + ) + + PropertyRegistry.register(list) + } +} 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/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..82f3513a77 --- /dev/null +++ b/library/src/main/java/com/nextcloud/operations/SearchMethod.kt @@ -0,0 +1,26 @@ +/* + * 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 fa872fe83d..584c692b5a 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 @@ -89,15 +89,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; @@ -185,7 +192,7 @@ public WebdavEntry(MultiStatusResponse ms, String splitElement) { if (prop!= null) { Object value = prop.getValue(); 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 @@ -515,7 +522,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/operations/RemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperation.java index 8d1c18d027..d6336eeb8c 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 @@ -447,11 +447,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..ae01331234 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,30 @@ 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.Permissions; 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 +60,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 +76,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 +87,78 @@ 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 Permissions) { + remoteFile.setPermissions(((Permissions) 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()); + } + } + + 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..a84bb25776 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,9 +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 java.util.concurrent.atomic.AtomicReference; + +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 +104,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 +127,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 +176,87 @@ 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(); + + AtomicReference davResponse = new AtomicReference<>(); + + 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); + return null; + }); + + // get data from remote folder + WebDavFileUtils webDavFileUtils = new WebDavFileUtils(); +// ArrayList mFolderAndFiles = webDavFileUtils.readData(davResponse.get(), +// client.getFilesDavUri()); + + 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/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/NCEtag.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/NCEtag.kt new file mode 100644 index 0000000000..e6e3b72950 --- /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..f5062aa961 --- /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..50c78bbf10 --- /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/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/files/webdav/Permissions.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/Permissions.kt new file mode 100644 index 0000000000..e53226771a --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/webdav/Permissions.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 Permissions 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) = + // + Permissions(XmlUtils.readText(parser) ?: "") + } +} 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 diff --git a/settings.gradle b/settings.gradle index eaae9a3945..a0ca01735c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,8 @@ include ':library' include ':sample_client' + +includeBuild('/home/tobi/projekt/github/bitfireAT/dav4jvm/') { + dependencySubstitution { + substitute module('com.github.bitfireAT:dav4jvm') using project(':') + } +}