Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -235,6 +239,6 @@ trigger:
- pull_request
---
kind: signature
hmac: 3e71a44f6f57a4d4d853c586c0c322bf0b718d96627906b92864e12353e5a014
hmac: fe00fcbb3bf41f6aa84193e380345c3b009ef933d295dda86ea3c959a8373381

...
Original file line number Diff line number Diff line change
@@ -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<String>()

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)
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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<List<FileDownloadLimit>>() {
@Deprecated("Deprecated in Java")
override fun run(client: OwnCloudClient): RemoteOperationResult<List<FileDownloadLimit>> {
val result: RemoteOperationResult<List<FileDownloadLimit>>
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
}
}
Original file line number Diff line number Diff line change
@@ -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<Void>() {
override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
val result: RemoteOperationResult<Void>

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"
}
}
Original file line number Diff line number Diff line change
@@ -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<Void>() {
override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
val result: RemoteOperationResult<Void>

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"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@ inline fun <reified T> 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
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions library/src/main/java/com/nextcloud/extensions/ParcelExtensions.kt
Original file line number Diff line number Diff line change
@@ -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 <reified T : Serializable?> 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
}
Loading
Loading