diff --git a/.drone.yml b/.drone.yml index 30eec7f8c7..39db790270 100644 --- a/.drone.yml +++ b/.drone.yml @@ -109,6 +109,8 @@ services: - su www-data -c "cd /var/www/html/apps/assistant; source ~/.bashrc; composer install --no-dev" - su www-data -c "php /var/www/html/occ app:enable -f assistant" - su www-data -c "php /var/www/html/occ app:enable -f testing" + - su www-data -c "git clone --depth 1 https://github.com/nextcloud/files_downloadlimit.git /var/www/html/apps/files_downloadlimit/" + - su www-data -c "php /var/www/html/occ app:enable -f files_downloadlimit" - /usr/local/bin/run.sh trigger: @@ -224,6 +226,8 @@ services: - su www-data -c "cd /var/www/html/apps/assistant; source ~/.bashrc; composer install --no-dev" - su www-data -c "php /var/www/html/occ app:enable assistant" - su www-data -c "php /var/www/html/occ app:enable -f testing" + - su www-data -c "git clone --depth 1 -b $SERVER_VERSION https://github.com/nextcloud/files_downloadlimit.git /var/www/html/apps/files_downloadlimit/" + - su www-data -c "php /var/www/html/occ app:enable -f files_downloadlimit" - /usr/local/bin/run.sh trigger: @@ -235,6 +239,6 @@ trigger: - pull_request --- kind: signature -hmac: 3e71a44f6f57a4d4d853c586c0c322bf0b718d96627906b92864e12353e5a014 +hmac: fe00fcbb3bf41f6aa84193e380345c3b009ef933d295dda86ea3c959a8373381 ... diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/FilesDownloadLimitIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/FilesDownloadLimitIT.kt new file mode 100644 index 0000000000..03c852d5b6 --- /dev/null +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/FilesDownloadLimitIT.kt @@ -0,0 +1,115 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.resources.files + +import com.nextcloud.android.lib.resources.files.GetFilesDownloadLimitRemoteOperation +import com.nextcloud.android.lib.resources.files.RemoveFilesDownloadLimitRemoteOperation +import com.nextcloud.android.lib.resources.files.SetFilesDownloadLimitRemoteOperation +import com.owncloud.android.AbstractIT +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.GetCapabilitiesRemoteOperation +import com.owncloud.android.lib.resources.status.NextcloudVersion +import com.owncloud.android.lib.resources.status.OCCapability +import junit.framework.TestCase.assertEquals +import org.junit.Before +import org.junit.Test + +class FilesDownloadLimitIT : AbstractIT() { + @Before + fun before() { + testOnlyOnServer(NextcloudVersion.nextcloud_30) + assert(getCapability().filesDownloadLimit.isTrue) + } + + @Test + fun getDefaultLimit() { + val defaultLimit = getCapability().filesDownloadLimitDefault + assertEquals(-1, defaultLimit) + } + + @Test + @Suppress("Detekt.MagicNumber") + fun downloadLimit() { + createTestFile() + + val shareTokens = mutableListOf() + + DOWNLOAD_LIMITS.forEach { limit -> + val share = createTestShare() + shareTokens.add(share.token!!) + + val resultSet = SetFilesDownloadLimitRemoteOperation(share.token!!, limit).execute(nextcloudClient) + assert(resultSet.isSuccess) + + shortSleep() + + val resultGet = GetFilesDownloadLimitRemoteOperation(REMOTE_PATH, false).execute(client) + assert(resultGet.isSuccess) + assertEquals(shareTokens.size, resultGet.resultData.size) + + val downloadLimit = + resultGet.resultData.first { + it.token == share.token + } + + assertEquals(limit, downloadLimit.limit) + assertEquals(0, downloadLimit.count) + } + + shortSleep() + + for (i in shareTokens.lastIndex downTo 0) { + val token = shareTokens[i] + val resultRemove = RemoveFilesDownloadLimitRemoteOperation(token).execute(nextcloudClient) + assert(resultRemove.isSuccess) + + shortSleep() + + val resultGet = GetFilesDownloadLimitRemoteOperation(REMOTE_PATH, false).execute(client) + assert(resultGet.isSuccess) + assertEquals(i, resultGet.resultData.size) + } + } + + private fun getCapability(): OCCapability = + GetCapabilitiesRemoteOperation().execute(nextcloudClient).singleData as OCCapability + + private fun createTestFile(): Boolean { + val localPath = createFile("test") + val result = + UploadFileRemoteOperation(localPath, REMOTE_PATH, "text/plain", RANDOM_MTIME) + .execute(client) + .isSuccess + assert(result) + return result + } + + private fun createTestShare(): OCShare { + val result = + CreateShareRemoteOperation( + REMOTE_PATH, + ShareType.PUBLIC_LINK, + "", + false, + "", + 1 + ).execute(client) + + assert(result.isSuccess) + val share = result.resultData.first() + assert(share.token != null) + return share + } + + companion object { + private const val REMOTE_PATH = "/downloadLimits.txt" + private val DOWNLOAD_LIMITS = listOf(5, 10) + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/files/FileDownloadLimit.kt b/library/src/main/java/com/nextcloud/android/lib/resources/files/FileDownloadLimit.kt new file mode 100644 index 0000000000..0718aec108 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/files/FileDownloadLimit.kt @@ -0,0 +1,16 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.files + +import java.io.Serializable + +data class FileDownloadLimit( + val token: String, + val limit: Int, + val count: Int +) : Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/files/GetFilesDownloadLimitRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/files/GetFilesDownloadLimitRemoteOperation.kt new file mode 100644 index 0000000000..ef429f6172 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/files/GetFilesDownloadLimitRemoteOperation.kt @@ -0,0 +1,67 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.files + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.network.WebdavEntry +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus +import org.apache.jackrabbit.webdav.DavConstants +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet +import org.apache.jackrabbit.webdav.xml.Namespace + +class GetFilesDownloadLimitRemoteOperation + @JvmOverloads + constructor( + val remotePath: String, + val subfiles: Boolean = false + ) : OCSRemoteOperation>() { + @Deprecated("Deprecated in Java") + override fun run(client: OwnCloudClient): RemoteOperationResult> { + val result: RemoteOperationResult> + val propSet = DavPropertyNameSet() + val depth = if (subfiles) DavConstants.DEPTH_1 else DavConstants.DEPTH_0 + + propSet.add( + WebdavEntry.EXTENDED_PROPERTY_FILE_DOWNLOAD_LIMITS, + Namespace.getNamespace(WebdavEntry.NAMESPACE_NC) + ) + + val propFindMethod = PropFindMethod(client.getFilesDavUri(remotePath), propSet, depth) + + val status = client.executeMethod(propFindMethod) + + if (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK) { + val response = propFindMethod.responseBodyAsMultiStatus + + val fileDownloadLimits = + response.responses.flatMap { + val webdavEntry = WebdavEntry(it, client.filesDavUri.encodedPath!!) + webdavEntry.fileDownloadLimit + } + + result = RemoteOperationResult(true, propFindMethod) + result.resultData = fileDownloadLimits + } else { + Log_OC.e(TAG, "Failed to get download limit") + result = RemoteOperationResult(false, propFindMethod) + client.exhaustResponse(propFindMethod.responseBodyAsStream) + } + + propFindMethod.releaseConnection() + + return result + } + + companion object { + private val TAG = GetFilesDownloadLimitRemoteOperation::class.java.simpleName + } + } diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/files/RemoveFilesDownloadLimitRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/files/RemoveFilesDownloadLimitRemoteOperation.kt new file mode 100644 index 0000000000..b2443c09a2 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/files/RemoveFilesDownloadLimitRemoteOperation.kt @@ -0,0 +1,45 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.files + +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.DeleteMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +class RemoveFilesDownloadLimitRemoteOperation( + val token: String +) : OCSRemoteOperation() { + override fun run(client: NextcloudClient): RemoteOperationResult { + val result: RemoteOperationResult + + val url = client.baseUri.toString() + String.format(FILES_DOWNLOAD_LIMIT_ENDPOINT, token) + JSON_FORMAT + val deleteMethod = DeleteMethod(url, true) + + val status = deleteMethod.execute(client) + + if (status == HttpStatus.SC_OK) { + result = RemoteOperationResult(true, deleteMethod) + } else { + result = RemoteOperationResult(false, deleteMethod) + Log_OC.e(TAG, "Failed to remove download limit") + Log_OC.e(TAG, "*** status code: " + status + "; response: " + deleteMethod.getResponseBodyAsString()) + } + + deleteMethod.releaseConnection() + + return result + } + + companion object { + private val TAG = RemoveFilesDownloadLimitRemoteOperation::class.java.simpleName + private const val FILES_DOWNLOAD_LIMIT_ENDPOINT = "/ocs/v2.php/apps/files_downloadlimit/api/v1/%s/limit" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/files/SetFilesDownloadLimitRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/files/SetFilesDownloadLimitRemoteOperation.kt new file mode 100644 index 0000000000..c22ce3863b --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/files/SetFilesDownloadLimitRemoteOperation.kt @@ -0,0 +1,48 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.files + +import com.nextcloud.common.JSONRequestBody +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.PutMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +class SetFilesDownloadLimitRemoteOperation( + val token: String, + val limit: Int +) : OCSRemoteOperation() { + override fun run(client: NextcloudClient): RemoteOperationResult { + val result: RemoteOperationResult + + val url = client.baseUri.toString() + String.format(FILES_DOWNLOAD_LIMIT_ENDPOINT, token) + val jsonRequestBody = JSONRequestBody("limit", limit.toString()) + val putMethod = PutMethod(url, true, jsonRequestBody.get()) + + val status = putMethod.execute(client) + + if (status == HttpStatus.SC_OK) { + result = RemoteOperationResult(true, putMethod) + } else { + result = RemoteOperationResult(false, putMethod) + Log_OC.e(TAG, "Failed to set download limit") + Log_OC.e(TAG, "*** status code: " + status + "; response: " + putMethod.getResponseBodyAsString()) + } + + putMethod.releaseConnection() + + return result + } + + companion object { + private val TAG = SetFilesDownloadLimitRemoteOperation::class.java.simpleName + private const val FILES_DOWNLOAD_LIMIT_ENDPOINT = "/ocs/v2.php/apps/files_downloadlimit/api/v1/%s/limit" + } +} diff --git a/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt b/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt index 4d36f58cb3..3e53e9b152 100644 --- a/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt +++ b/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt @@ -16,17 +16,14 @@ inline fun ArrayList<*>.processXmlData(tagName: String): T? { val element = it as? Element if (element != null && element.tagName == tagName) { val textContent = element.firstChild.textContent - return when (T::class) { Float::class -> { - val floatValue = textContent.toFloatOrNull() - if (floatValue != null) floatValue as T else null + textContent.toFloatOrNull() as? T } Double::class -> { - val doubleValue = textContent.toDoubleOrNull() - if (doubleValue != null) doubleValue as T else null + textContent.toDoubleOrNull() as? T } - else -> return null + else -> textContent as? T } } } diff --git a/library/src/main/java/com/nextcloud/extensions/ParcelExtensions.kt b/library/src/main/java/com/nextcloud/extensions/ParcelExtensions.kt new file mode 100644 index 0000000000..ae1957b927 --- /dev/null +++ b/library/src/main/java/com/nextcloud/extensions/ParcelExtensions.kt @@ -0,0 +1,20 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2024 ZetaTom <70907959+zetatom@users.noreply.github.com> + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.extensions + +import android.os.Build +import android.os.Parcel +import java.io.Serializable + +inline fun Parcel.readSerializableCompat(): T? = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + readSerializable(T::class.java.classLoader, T::class.java) + } else { + @Suppress("DEPRECATION") + readSerializable() as? T + } diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 442fda4c3d..978a3e9651 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -11,6 +11,7 @@ package com.owncloud.android.lib.common.network import android.net.Uri import com.google.gson.Gson +import com.nextcloud.android.lib.resources.files.FileDownloadLimit import com.nextcloud.extensions.fromDavProperty import com.nextcloud.extensions.processXmlData import com.owncloud.android.lib.common.utils.Log_OC @@ -96,6 +97,7 @@ class WebdavEntry constructor( private set var livePhoto: String? = null private set + var fileDownloadLimit = emptyList() private val gson = Gson() @@ -114,7 +116,7 @@ class WebdavEntry constructor( path = uri!!.split(splitElement.toRegex(), limit = 2).toTypedArray()[1].replace("//", "/") var status = ms.status[0].statusCode - if (status == CODE_PROP_NOT_FOUND) { + if (status == CODE_PROP_NOT_FOUND && ms.status.size > 1) { status = ms.status[1].statusCode } val propSet = ms.getProperties(status) @@ -464,6 +466,19 @@ class WebdavEntry constructor( false } + // NC files download limits property: + prop = propSet[EXTENDED_PROPERTY_FILE_DOWNLOAD_LIMITS, ncNamespace] + if (prop != null && prop.value != null) { + if (prop.value is ArrayList<*>) { + val list = prop.value as ArrayList<*> + fileDownloadLimit = list.mapNotNull { extractFileDownloadLimit(it as Element) } + } else { + extractFileDownloadLimit(prop.value as Element)?.let { + fileDownloadLimit = listOf(it) + } + } + } + parseLockProperties(ncNamespace, propSet) } else { Log_OC.e("WebdavEntry", "General error, no status for webdav response") @@ -564,6 +579,35 @@ class WebdavEntry constructor( return ShareType.NO_SHARED } + private fun extractFileDownloadLimit(element: Element): FileDownloadLimit? { + val token = + element + .getElementsByTagNameNS(NAMESPACE_NC, "token") + ?.item(0) + ?.firstChild + ?.nodeValue + val limit = + element + .getElementsByTagNameNS(NAMESPACE_NC, "limit") + ?.item(0) + ?.firstChild + ?.nodeValue + ?.toIntOrNull() + val count = + element + .getElementsByTagNameNS(NAMESPACE_NC, "count") + ?.item(0) + ?.firstChild + ?.nodeValue + ?.toIntOrNull() + + return if (token != null && limit != null && count != null) { + FileDownloadLimit(token, limit, count) + } else { + null + } + } + fun decodedPath(): String = Uri.decode(path) val isDirectory: Boolean @@ -623,6 +667,8 @@ class WebdavEntry constructor( const val EXTENDED_PROPERTY_HIDDEN = "hidden" const val EXTENDED_PROPERTY_METADATA_LIVE_PHOTO = "metadata-files-live-photo" + const val EXTENDED_PROPERTY_FILE_DOWNLOAD_LIMITS = "share-download-limits" + const val EXTENDED_PROPERTY_METADATA_PHOTOS_SIZE = "metadata-photos-size" const val EXTENDED_PROPERTY_METADATA_PHOTOS_GPS = "metadata-photos-gps" const val TRASHBIN_FILENAME = "trashbin-filename" 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 40cd11fea2..e15e02b0f8 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 @@ -123,6 +123,7 @@ public static DavPropertyNameSet getAllPropSet() { propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_GPS, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_LIVE_PHOTO, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_HIDDEN, ncNamespace); + propSet.add(WebdavEntry.EXTENDED_PROPERTY_FILE_DOWNLOAD_LIMITS, ncNamespace); return propSet; } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index f35e1304f2..052ce8e14a 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -8,6 +8,7 @@ package com.owncloud.android.lib.resources.files.model import android.os.Parcel import android.os.Parcelable +import com.nextcloud.android.lib.resources.files.FileDownloadLimit import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.common.network.WebdavEntry.MountType import com.owncloud.android.lib.resources.files.FileUtils @@ -57,6 +58,7 @@ class RemoteFile : var geoLocation: GeoLocation? = null var hidden = false var livePhoto: String? = null + var fileDownloadLimit: List = emptyList() constructor() { resetData() @@ -112,6 +114,7 @@ class RemoteFile : geoLocation = we.geoLocation livePhoto = we.livePhoto hidden = we.hidden + fileDownloadLimit = we.fileDownloadLimit } /** @@ -144,6 +147,7 @@ class RemoteFile : tags = null hidden = false livePhoto = null + fileDownloadLimit = emptyList() } /** diff --git a/library/src/main/java/com/owncloud/android/lib/resources/shares/GetSharesForFileRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/shares/GetSharesForFileRemoteOperation.java index b579e65ba9..8ee72cc598 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/shares/GetSharesForFileRemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/shares/GetSharesForFileRemoteOperation.java @@ -19,12 +19,14 @@ import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; +import java.util.List; + /** * Provide a list shares for a specific file. * The input is the full path of the desired file. * The output is a list of everyone who has the file shared with them. */ -public class GetSharesForFileRemoteOperation extends RemoteOperation { +public class GetSharesForFileRemoteOperation extends RemoteOperation> { private static final String TAG = GetSharesForFileRemoteOperation.class.getSimpleName(); @@ -32,9 +34,9 @@ public class GetSharesForFileRemoteOperation extends RemoteOperation { private static final String PARAM_RESHARES = "reshares"; private static final String PARAM_SUBFILES = "subfiles"; - private String mRemoteFilePath; - private boolean mReshares; - private boolean mSubfiles; + private final String mRemoteFilePath; + private final boolean mReshares; + private final boolean mSubfiles; /** * Constructor @@ -46,17 +48,15 @@ public class GetSharesForFileRemoteOperation extends RemoteOperation { * @param subfiles If set to false (default), lists only the folder being shared * If set to true, all shared files within the folder are returned. */ - public GetSharesForFileRemoteOperation(String remoteFilePath, boolean reshares, - boolean subfiles) { + public GetSharesForFileRemoteOperation(String remoteFilePath, boolean reshares, boolean subfiles) { mRemoteFilePath = remoteFilePath; mReshares = reshares; mSubfiles = subfiles; } @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = null; - int status = -1; + protected RemoteOperationResult> run(OwnCloudClient client) { + RemoteOperationResult> result; GetMethod get = null; @@ -68,13 +68,12 @@ protected RemoteOperationResult run(OwnCloudClient client) { get.setQueryString(new NameValuePair[]{ new NameValuePair(PARAM_PATH, mRemoteFilePath), new NameValuePair(PARAM_RESHARES, String.valueOf(mReshares)), - new NameValuePair(PARAM_SUBFILES, String.valueOf(mSubfiles)) //, - //new NameValuePair("shared_with_me", "true") + new NameValuePair(PARAM_SUBFILES, String.valueOf(mSubfiles)) }); get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); - status = client.executeMethod(get); + int status = client.executeMethod(get); if (isSuccess(status)) { String response = get.getResponseBodyAsString(); @@ -91,11 +90,11 @@ protected RemoteOperationResult run(OwnCloudClient client) { } } else { - result = new RemoteOperationResult(false, get); + result = new RemoteOperationResult<>(false, get); } } catch (Exception e) { - result = new RemoteOperationResult(e); + result = new RemoteOperationResult<>(e); Log_OC.e(TAG, "Exception while getting shares", e); } finally { diff --git a/library/src/main/java/com/owncloud/android/lib/resources/shares/OCShare.kt b/library/src/main/java/com/owncloud/android/lib/resources/shares/OCShare.kt index 76f46e9c5d..31aacfa9b4 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/shares/OCShare.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/shares/OCShare.kt @@ -12,6 +12,8 @@ package com.owncloud.android.lib.resources.shares import android.os.Parcel import android.os.Parcelable +import com.nextcloud.android.lib.resources.files.FileDownloadLimit +import com.nextcloud.extensions.readSerializableCompat import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.resources.files.FileUtils import java.io.Serializable @@ -70,6 +72,7 @@ class OCShare : var mimetype: String? = null var ownerDisplayName: String? = null var isFavorite = false + var fileDownloadLimit: FileDownloadLimit? = null constructor() : super() { resetData() @@ -110,6 +113,7 @@ class OCShare : isHasPreview = false mimetype = "" ownerDisplayName = "" + fileDownloadLimit = null } /** @@ -149,6 +153,7 @@ class OCShare : isHasPreview = source.readInt() == 1 mimetype = source.readString() ownerDisplayName = source.readString() + fileDownloadLimit = source.readSerializableCompat() } override fun describeContents(): Int = this.hashCode() @@ -178,6 +183,7 @@ class OCShare : dest.writeInt(if (isHasPreview) 1 else 0) dest.writeString(mimetype) dest.writeString(ownerDisplayName) + dest.writeSerializable(fileDownloadLimit) } companion object { diff --git a/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java index acd225b18e..5a5c3f7068 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java @@ -166,6 +166,10 @@ public class GetCapabilitiesRemoteOperation extends RemoteOperation { private static final String FORBIDDEN_FILENAME_EXTENSIONS = "forbidden_filename_extensions"; private static final String FORBIDDEN_FILENAME_BASE_NAMES = "forbidden_filename_basenames"; + // files download limits + private static final String NODE_FILES_DOWNLOAD_LIMIT = "downloadlimit"; + private static final String FILES_DOWNLOAD_LIMIT_DEFAULT = "default-limit"; + private OCCapability currentCapability = null; public GetCapabilitiesRemoteOperation() { @@ -734,6 +738,22 @@ private OCCapability parseResponse(String response) throws JSONException { } else { capability.setSecurityGuard(CapabilityBooleanType.FALSE); } + + // files download limits + if (respCapabilities.has(NODE_FILES_DOWNLOAD_LIMIT)) { + JSONObject filesDownloadLimitCapability = respCapabilities.getJSONObject(NODE_FILES_DOWNLOAD_LIMIT); + + if (filesDownloadLimitCapability.getBoolean(PROPERTY_ENABLED)) { + capability.setFilesDownloadLimit(CapabilityBooleanType.TRUE); + } else { + capability.setFilesDownloadLimit(CapabilityBooleanType.FALSE); + } + + if (filesDownloadLimitCapability.has(FILES_DOWNLOAD_LIMIT_DEFAULT)) { + int defaultDownloadLimit = filesDownloadLimitCapability.getInt(FILES_DOWNLOAD_LIMIT_DEFAULT); + capability.setFilesDownloadLimitDefault(defaultDownloadLimit); + } + } } Log_OC.d(TAG, "*** Get Capabilities completed "); 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 e6bdf3903b..0ba53fe14d 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 @@ -110,6 +110,10 @@ class OCCapability { var forbiddenFilenameExtensionJson: String? = null var forbiddenFilenameBaseNamesJson: String? = null + // files download limits + var filesDownloadLimit = CapabilityBooleanType.UNKNOWN + var filesDownloadLimitDefault = -1 + // Etag for capabilities var etag: String? = ""