diff --git a/.drone.yml b/.drone.yml index 5c97b452b2..67bdf02e5d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -99,6 +99,8 @@ services: - su www-data -c "git clone https://github.com/nextcloud/photos.git /var/www/html/apps/photos/" - su www-data -c "cd /var/www/html/apps/photos; composer install" - su www-data -c "php /var/www/html/occ app:enable -f photos" + - su www-data -c "git clone 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: diff --git a/library/src/androidTest/java/com/owncloud/android/lib/common/operations/CreateShareIT.java b/library/src/androidTest/java/com/owncloud/android/lib/common/operations/CreateShareIT.java index 7b48744846..cdf6c428ac 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/common/operations/CreateShareIT.java +++ b/library/src/androidTest/java/com/owncloud/android/lib/common/operations/CreateShareIT.java @@ -28,18 +28,25 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import com.owncloud.android.AbstractIT; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.download_limit.GetShareDownloadLimitOperation; +import com.owncloud.android.lib.resources.download_limit.UpdateShareDownloadLimitRemoteOperation; +import com.owncloud.android.lib.resources.download_limit.model.DownloadLimitResponse; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; 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.NextcloudVersion; import org.junit.Before; import org.junit.Test; import java.io.File; +import java.util.List; /** * Test create share @@ -246,4 +253,36 @@ public void testCreateFederatedShareWithNonExistingFile() { assertFalse("file doesn't exist", result.isSuccess()); assertEquals("file doesn't exist", ResultCode.FILE_NOT_FOUND, result.getCode()); } + + @Test + public void testCreatePublicShareWithDownloadLimit() { + testOnlyOnServer(NextcloudVersion.nextcloud_25); + + int downloadLimit = 5; + CreateShareRemoteOperation operation = new CreateShareRemoteOperation( + mFullPath2FileToShare, + ShareType.PUBLIC_LINK, + "", + false, + "", + 1); + operation.setGetShareDetails(true); + RemoteOperationResult> result = operation.execute(client); + assertTrue(result.isSuccess()); + String shareToken = result.getResultData().get(0).getToken(); + assertNotNull(shareToken); + + assertTrue(new UpdateShareDownloadLimitRemoteOperation(shareToken, downloadLimit) + .execute(client) + .isSuccess() + ); + + RemoteOperationResult limitOperation = + new GetShareDownloadLimitOperation(shareToken) + .execute(client); + + assertTrue(limitOperation.isSuccess()); + assertEquals(downloadLimit, limitOperation.getResultData().getLimit()); + assertEquals(0, limitOperation.getResultData().getCount()); + } } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParserIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParserIT.kt new file mode 100644 index 0000000000..86ee443c5e --- /dev/null +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParserIT.kt @@ -0,0 +1,118 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +import org.junit.Assert.* +import org.junit.Test + +class DownloadLimitXMLParserIT { + + @Test + fun parseSuccessResponseWithValues(){ + val xml = """ + + + ok + 200 + OK + + + 5 + 1 + + + """ + + val remoteOperationResult = DownloadLimitXMLParser().parse(true, xml) + + assertTrue(remoteOperationResult.isSuccess) + assertEquals(5, remoteOperationResult.resultData.limit) + assertEquals(1, remoteOperationResult.resultData.count) + } + + + @Test + fun parseSuccessResponseWithNoValues(){ + val xml = """ + + + ok + 200 + OK + + + + + + + """ + + val remoteOperationResult = DownloadLimitXMLParser().parse(true, xml) + + assertTrue(remoteOperationResult.isSuccess) + assertEquals(0, remoteOperationResult.resultData.limit) + assertEquals(0, remoteOperationResult.resultData.count) + } + + @Test + fun parseSuccessResponseForUpdateDeleteOperations(){ + val xml = """ + + + ok + 200 + OK + + + + """ + + val remoteOperationResult = DownloadLimitXMLParser().parse(true, xml) + + assertTrue(remoteOperationResult.isSuccess) + } + + @Test + fun parseFailResponse(){ + val xml = """ + + + ok + 403 + OK + + + + """ + + val remoteOperationResult = DownloadLimitXMLParser().parse(true, xml) + + assertFalse(remoteOperationResult.isSuccess) + } + +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DeleteShareDownloadLimitRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DeleteShareDownloadLimitRemoteOperation.kt new file mode 100644 index 0000000000..4ab78d25e4 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DeleteShareDownloadLimitRemoteOperation.kt @@ -0,0 +1,87 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperation +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.download_limit.model.DownloadLimitResponse +import org.apache.commons.httpclient.HttpStatus +import org.apache.commons.httpclient.methods.DeleteMethod + +/** + * class to delete the download limit for the link share + * this has to be executed when user has toggled off the download limit + * + * + * API : //DELETE to /ocs/v2.php/apps/files_downloadlimit/{share_token}/limit + */ +class DeleteShareDownloadLimitRemoteOperation(private val shareToken: String) : + RemoteOperation() { + override fun run(client: OwnCloudClient): RemoteOperationResult { + var result: RemoteOperationResult + val status: Int + var deleteMethod: DeleteMethod? = null + try { + // Post Method + deleteMethod = DeleteMethod( + client.baseUri.toString() + ShareDownloadLimitUtils.getDownloadLimitApiPath( + shareToken + ) + ) + deleteMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + status = client.executeMethod(deleteMethod) + if (isSuccess(status)) { + val response = deleteMethod.responseBodyAsString + Log_OC.d(TAG, "Delete Download Limit response: $response") + val parser = DownloadLimitXMLParser() + result = parser.parse(true, response) + if (result.isSuccess) { + return result + } + } else { + result = RemoteOperationResult(false, deleteMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e(TAG, "Exception while deleting share download limit", e) + } finally { + deleteMethod?.releaseConnection() + } + return result + } + + private fun isSuccess(status: Int): Boolean { + return status == HttpStatus.SC_OK || status == HttpStatus.SC_BAD_REQUEST + } + + companion object { + private val TAG = DeleteShareDownloadLimitRemoteOperation::class.java.simpleName + } +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParser.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParser.kt new file mode 100644 index 0000000000..ab63ee3e35 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/DownloadLimitXMLParser.kt @@ -0,0 +1,291 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +import android.util.Xml +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.download_limit.model.DownloadLimitResponse +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import org.xmlpull.v1.XmlPullParserFactory +import java.io.ByteArrayInputStream +import java.io.IOException +import java.io.InputStream + +/** + * class to parse the Download Limit api XML response This class code referenced from java in NC library + */ +class DownloadLimitXMLParser { + // Getters and Setters + var status: String? = null + var statusCode = 0 + var message = "" + val isSuccess: Boolean + get() = statusCode == SUCCESS || statusCode == OK + private val isForbidden: Boolean + get() = statusCode == ERROR_FORBIDDEN + private val isNotFound: Boolean + get() = statusCode == ERROR_NOT_FOUND + private val isWrongParameter: Boolean + get() = statusCode == ERROR_WRONG_PARAMETER + + /** + * method to parse the Download limit response + * @param isGet check if parsing has to do for GET api or not + * because the parsing will depend on that + * if API is GET then response will have tag else it wont have + * @param serverResponse + * @return + */ + fun parse(isGet: Boolean, serverResponse: String?): RemoteOperationResult { + if (serverResponse == null || serverResponse.isEmpty()) { + return RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE) + } + var result: RemoteOperationResult + try { + // Parse xml response and obtain the list of downloadLimitResponse + val inputStream: InputStream = ByteArrayInputStream(serverResponse.toByteArray()) + val downloadLimitResponse = parseXMLResponse(inputStream) + if (isSuccess) { + if (isGet) { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.OK) + result.setResultData(downloadLimitResponse) + } else { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE) + Log_OC.e(TAG, "Successful status with no share in the response") + } + } else if (isWrongParameter) { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER) + result.setMessage(message) + } else if (isNotFound) { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND) + result.setMessage(message) + } else if (isForbidden) { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_FORBIDDEN) + result.setMessage(message) + } else { + result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE) + result.setMessage(message) + } + } catch (e: XmlPullParserException) { + Log_OC.e(TAG, "Error parsing response from server ", e) + result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE) + } catch (e: IOException) { + Log_OC.e(TAG, "Error reading response from server ", e) + result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE) + } + return result + } + + /** + * Parse is as response of Share API + * + * @param `is` InputStream to parse + * @return List of ShareRemoteFiles + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun parseXMLResponse(inputStream: InputStream): DownloadLimitResponse { + return inputStream.use { + // XMLPullParser + val factory = XmlPullParserFactory.newInstance() + factory.isNamespaceAware = true + val parser = Xml.newPullParser() + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false) + parser.setInput(it, null) + parser.nextTag() + readOCS(parser) + } + } + + /** + * Parse OCS node + * + * @param parser + * @return List of ShareRemoteFiles + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun readOCS(parser: XmlPullParser): DownloadLimitResponse { + var downloadLimitResponse = DownloadLimitResponse() + parser.require(XmlPullParser.START_TAG, ns, NODE_OCS) + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.eventType != XmlPullParser.START_TAG) { + continue + } + val name = parser.name + // read NODE_META and NODE_DATA + if (NODE_META.equals(name, ignoreCase = true)) { + readMeta(parser) + } else if (NODE_DATA.equals(name, ignoreCase = true)) { + downloadLimitResponse = readData(parser) + } else { + skip(parser) + } + } + return downloadLimitResponse + } + + /** + * Parse Meta node + * + * @param parser + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun readMeta(parser: XmlPullParser) { + parser.require(XmlPullParser.START_TAG, ns, NODE_META) + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.eventType != XmlPullParser.START_TAG) { + continue + } + val name = parser.name + if (NODE_STATUS.equals(name, ignoreCase = true)) { + status = readNode(parser, NODE_STATUS) + } else if (NODE_STATUS_CODE.equals(name, ignoreCase = true)) { + statusCode = readNode(parser, NODE_STATUS_CODE).toInt() + } else if (NODE_MESSAGE.equals(name, ignoreCase = true)) { + message = readNode(parser, NODE_MESSAGE) + } else { + skip(parser) + } + } + } + + /** + * Parse Data node + * + * @param parser + * @return + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun readData(parser: XmlPullParser): DownloadLimitResponse { + val downloadLimitResponse = DownloadLimitResponse() + parser.require(XmlPullParser.START_TAG, ns, NODE_DATA) + //Log_OC.d(TAG, "---- NODE DATA ---"); + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.eventType != XmlPullParser.START_TAG) { + continue + } + val name = parser.name + if (NODE_LIMIT.equals(name, ignoreCase = true)) { + val downloadLimit = readNode(parser, NODE_LIMIT) + downloadLimitResponse.limit = if (downloadLimit.isNotEmpty()) downloadLimit.toLong() else 0L + } else if (NODE_COUNT.equals(name, ignoreCase = true)) { + val downloadCount = readNode(parser, NODE_COUNT) + downloadLimitResponse.count = if (downloadCount.isNotEmpty()) downloadCount.toLong() else 0L + } else { + skip(parser) + } + } + return downloadLimitResponse + } + + /** + * Parse a node, to obtain its text. Needs readText method + * + * @param parser + * @param node + * @return Text of the node + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun readNode(parser: XmlPullParser, node: String): String { + parser.require(XmlPullParser.START_TAG, ns, node) + val value = readText(parser) + //Log_OC.d(TAG, "node= " + node + ", value= " + value); + parser.require(XmlPullParser.END_TAG, ns, node) + return value + } + + /** + * Read the text from a node + * + * @param parser + * @return Text of the node + * @throws IOException + * @throws XmlPullParserException + */ + @Throws(IOException::class, XmlPullParserException::class) + private fun readText(parser: XmlPullParser): String { + var result = "" + if (parser.next() == XmlPullParser.TEXT) { + result = parser.text + parser.nextTag() + } + return result + } + + /** + * Skip tags in parser procedure + * + * @param parser + * @throws XmlPullParserException + * @throws IOException + */ + @Throws(XmlPullParserException::class, IOException::class) + private fun skip(parser: XmlPullParser) { + check(parser.eventType == XmlPullParser.START_TAG) + var depth = 1 + while (depth != 0) { + when (parser.next()) { + XmlPullParser.END_TAG -> depth-- + XmlPullParser.START_TAG -> depth++ + } + } + } + + companion object { + private val TAG = DownloadLimitXMLParser::class.java.simpleName + + // No namespaces + private val ns: String? = null + + // NODES for XML Parser + private const val NODE_OCS = "ocs" + private const val NODE_META = "meta" + private const val NODE_STATUS = "status" + private const val NODE_STATUS_CODE = "statuscode" + private const val NODE_MESSAGE = "message" + private const val NODE_DATA = "data" + private const val NODE_LIMIT = "limit" + private const val NODE_COUNT = "count" + private const val SUCCESS = 100 + private const val OK = 200 + private const val ERROR_WRONG_PARAMETER = 400 + private const val ERROR_FORBIDDEN = 403 + private const val ERROR_NOT_FOUND = 404 + } +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/GetShareDownloadLimitOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/GetShareDownloadLimitOperation.kt new file mode 100644 index 0000000000..1b51d5be70 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/GetShareDownloadLimitOperation.kt @@ -0,0 +1,89 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperation +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.download_limit.model.DownloadLimitResponse +import com.owncloud.android.lib.resources.download_limit.ShareDownloadLimitUtils.getDownloadLimitApiPath +import org.apache.commons.httpclient.HttpStatus +import org.apache.commons.httpclient.methods.GetMethod + +/** + * class to fetch the download limit for the link share it requires share token to fetch the data + * + * + * API : //GET to /ocs/v2.php/apps/files_downloadlimit/{share_token}/limit + */ +class GetShareDownloadLimitOperation( + //share token from OCShare + private val shareToken: String +) : RemoteOperation() { + override fun run(client: OwnCloudClient): RemoteOperationResult { + var result: RemoteOperationResult + var status = -1 + var get: GetMethod? = null + try { + // Get Method + get = GetMethod( + client.baseUri.toString() + getDownloadLimitApiPath( + shareToken + ) + ) + get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + status = client.executeMethod(get) + if (isSuccess(status)) { + val response = get.responseBodyAsString + Log_OC.d(TAG, "Get Download Limit response: $response") + val parser = DownloadLimitXMLParser() + result = parser.parse(true, response) + if (result.isSuccess) { + Log_OC.d(TAG, "Got " + result.resultData + " Response") + } + } else { + result = RemoteOperationResult(false, get) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e(TAG, "Exception while getting share download limit", e) + } finally { + get?.releaseConnection() + } + return result + } + + private fun isSuccess(status: Int): Boolean { + return status == HttpStatus.SC_OK + } + + companion object { + private val TAG = GetShareDownloadLimitOperation::class.java.simpleName + } +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/ShareDownloadLimitUtils.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/ShareDownloadLimitUtils.kt new file mode 100644 index 0000000000..ec6e0357e8 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/ShareDownloadLimitUtils.kt @@ -0,0 +1,41 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +object ShareDownloadLimitUtils { + + private const val SHARE_TOKEN_PATH = "{share_token}" + + //ocs route + //replace the {share_token} + private const val SHARE_DOWNLOAD_LIMIT_API_PATH = "/ocs/v2.php/apps/files_downloadlimit/$SHARE_TOKEN_PATH/limit" + + fun getDownloadLimitApiPath(shareToken: String): String { + return SHARE_DOWNLOAD_LIMIT_API_PATH.replace(SHARE_TOKEN_PATH, shareToken) + } +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/UpdateShareDownloadLimitRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/UpdateShareDownloadLimitRemoteOperation.kt new file mode 100644 index 0000000000..3cf504f88a --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/UpdateShareDownloadLimitRemoteOperation.kt @@ -0,0 +1,106 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit + +import android.util.Pair +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperation +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.download_limit.model.DownloadLimitResponse +import com.owncloud.android.lib.resources.download_limit.ShareDownloadLimitUtils.getDownloadLimitApiPath +import org.apache.commons.httpclient.HttpStatus +import org.apache.commons.httpclient.methods.PutMethod +import org.apache.commons.httpclient.methods.StringRequestEntity + +/** + * class to update the download limit for the link share + * + * + * API : //PUT to /ocs/v2.php/apps/files_downloadlimit/{share_token}/limit + * + * + * Body: {"token" : "Bpd4oEAgPqn3AbG", "limit" : 5} + */ +class UpdateShareDownloadLimitRemoteOperation(private val shareToken: String, private val downloadLimit: Long) : + RemoteOperation() { + override fun run(client: OwnCloudClient): RemoteOperationResult { + var result: RemoteOperationResult + val status: Int + var put: PutMethod? = null + try { + // Post Method + put = PutMethod( + client.baseUri.toString() + getDownloadLimitApiPath( + shareToken + ) + ) + put.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + val parametersToUpdate: MutableList> = ArrayList() + parametersToUpdate.add(Pair(PARAM_TOKEN, shareToken)) + parametersToUpdate.add(Pair(PARAM_LIMIT, downloadLimit.toString())) + for (parameter in parametersToUpdate) { + put.requestEntity = StringRequestEntity( + parameter.first + "=" + parameter.second, + ENTITY_CONTENT_TYPE, + ENTITY_CHARSET + ) + } + status = client.executeMethod(put) + if (isSuccess(status)) { + val response = put.responseBodyAsString + Log_OC.d(TAG, "Download Limit response: $response") + val parser = DownloadLimitXMLParser() + result = parser.parse(true, response) + if (result.isSuccess) { + return result + } + } else { + result = RemoteOperationResult(false, put) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e(TAG, "Exception while updating share download limit", e) + } finally { + put?.releaseConnection() + } + return result + } + + private fun isSuccess(status: Int): Boolean { + return status == HttpStatus.SC_OK || status == HttpStatus.SC_BAD_REQUEST + } + + companion object { + private val TAG = UpdateShareDownloadLimitRemoteOperation::class.java.simpleName + private const val PARAM_TOKEN = "token" + private const val PARAM_LIMIT = "limit" + private const val ENTITY_CONTENT_TYPE = "application/x-www-form-urlencoded" + private const val ENTITY_CHARSET = "UTF-8" + } +} \ No newline at end of file diff --git a/library/src/main/java/com/owncloud/android/lib/resources/download_limit/model/DownloadLimitResponse.kt b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/model/DownloadLimitResponse.kt new file mode 100644 index 0000000000..0fbac2b44b --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/download_limit/model/DownloadLimitResponse.kt @@ -0,0 +1,45 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author TSI-mc + * Copyright (C) 2023 TSI-mc + * Copyright (C) 2023 Nextcloud GmbH + * + * 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, + * 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 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.download_limit.model + +/** + * response from the Get download limit api + * + * + * + * ok + * 200 + * OK + * + * + * 5 + * 0 + * + * + */ +data class DownloadLimitResponse(var limit: Long = 0, var count: Long = 0) \ No newline at end of file