From 4b6946a19536fd76bfb284909e109804d0ebfdae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 13 Oct 2020 10:42:40 +0200 Subject: [PATCH 01/41] Update dependencies and perform a little cleanup --- build.gradle | 5 ++--- owncloudComLibrary/build.gradle | 6 ------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index f51df2b2..07767bc9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlinVersion = '1.3.72' + kotlinVersion = '1.4.10' moshiVersion = "1.9.2" } @@ -9,9 +9,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion" } } diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 8aac2c83..6db1f790 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -1,7 +1,6 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' -apply plugin: 'kotlin-allopen' dependencies { api 'com.squareup.okhttp3:okhttp:4.6.0' @@ -17,11 +16,6 @@ dependencies { kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" } -allOpen { - // allows mocking for classes w/o directly opening them for release builds - annotation 'com.owncloud.android.lib.testing.OpenClass' -} - android { compileSdkVersion 29 From 775fdb080cc3deb7b628925f77870060e1eb0cf3 Mon Sep 17 00:00:00 2001 From: agarcia Date: Wed, 30 Sep 2020 16:43:38 +0200 Subject: [PATCH 02/41] Add first draft to log network calls --- .../android/lib/common/http/HttpClient.java | 9 +++ .../android/lib/common/http/LogBuilder.kt | 39 +++++++++++++ .../android/lib/common/http/LogInterceptor.kt | 57 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 12571a88..517dd56a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -57,6 +57,7 @@ public class HttpClient { private static OkHttpClient sOkHttpClient; private static Context sContext; private static HashMap> sCookieStore = new HashMap<>(); + private static LogInterceptor sLogInterceptor; public static OkHttpClient getOkHttpClient() { if (sOkHttpClient == null) { @@ -111,6 +112,7 @@ public class HttpClient { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .protocols(Arrays.asList(Protocol.HTTP_1_1)) + .addInterceptor(getLogInterceptor()) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) @@ -137,6 +139,13 @@ public class HttpClient { sContext = context; } + public static LogInterceptor getLogInterceptor() { + if (sLogInterceptor == null) { + sLogInterceptor = new LogInterceptor(); + } + return sLogInterceptor; + } + public List getCookiesFromUrl(HttpUrl httpUrl) { return sCookieStore.get(httpUrl.host()); } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt new file mode 100644 index 00000000..ef9df143 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -0,0 +1,39 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2020 ownCloud 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.common.http + +object LogBuilder { + fun toLogString( + networkPetition: NetworkPetition, + networkNode: NetworkNode, + description: String + ): String = "[Network, $networkPetition] [$networkNode] $description" +} + +enum class NetworkPetition { + REQUEST, RESPONSE +} + +enum class NetworkNode { + INFO, HEADER, BODY +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt new file mode 100644 index 00000000..89fa09bd --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -0,0 +1,57 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2020 ownCloud 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.common.http + +import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import okhttp3.Interceptor +import okhttp3.Response +import timber.log.Timber + +class LogInterceptor : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + // Log request + chain.request().let { + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.INFO, "Type: ${it.method} URL: ${it.url}")) + it.headers.forEach { header -> + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.HEADER, header.toString())) + } + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.BODY, it.body.toString())) + } + + val response = chain.proceed(chain.request()) + + // Log response + response.let { + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}")) + it.headers.forEach { header -> + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.HEADER, header.toString())) + } + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.BODY, it.body.toString())) + } + + return response + } +} From a564f18f161a0079a83835577d22ab73491a64d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Fri, 2 Oct 2020 14:38:38 +0200 Subject: [PATCH 03/41] Http logs enabled only in debug versions --- .../com/owncloud/android/lib/common/http/HttpClient.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 517dd56a..9aab751a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -26,6 +26,7 @@ package com.owncloud.android.lib.common.http; import android.content.Context; +import com.owncloud.android.lib.BuildConfig; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.NetworkUtils; import okhttp3.Cookie; @@ -112,7 +113,6 @@ public class HttpClient { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .protocols(Arrays.asList(Protocol.HTTP_1_1)) - .addInterceptor(getLogInterceptor()) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) @@ -122,6 +122,12 @@ public class HttpClient { .cookieJar(cookieJar); // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); + + // Http logs enabled only in debug version. TODO: Add an option to enable and disable it. + if (BuildConfig.DEBUG) { + clientBuilder.addInterceptor(getLogInterceptor()); + } + sOkHttpClient = clientBuilder.build(); } catch (Exception e) { From dc215dc80e344dd93b42109dceacf352c3e8d21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Mon, 5 Oct 2020 13:19:38 +0200 Subject: [PATCH 04/41] Add a new variable to enable or disable http logs --- .../android/lib/common/http/LogInterceptor.kt | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 89fa09bd..400b6120 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -24,6 +24,8 @@ package com.owncloud.android.lib.common.http import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import com.owncloud.android.lib.common.http.NetworkNode.* +import com.owncloud.android.lib.common.http.NetworkPetition.* import okhttp3.Interceptor import okhttp3.Response import timber.log.Timber @@ -31,27 +33,39 @@ import timber.log.Timber class LogInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { - // Log request - chain.request().let { - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.INFO, "Type: ${it.method} URL: ${it.url}")) - it.headers.forEach { header -> - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.HEADER, header.toString())) - } - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.BODY, it.body.toString())) - } val response = chain.proceed(chain.request()) - // Log response - response.let { - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}")) - it.headers.forEach { header -> - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.HEADER, header.toString())) - } - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.BODY, it.body.toString())) - } + return response.also { + if (httpLogsEnabled) { + // Log request + Timber.d( + toLogString(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") + ) + it.headers.forEach { header -> + Timber.d(toLogString(REQUEST, HEADER, header.toString())) + } + Timber.d(toLogString(REQUEST, BODY, it.body.toString())) - return response + // Log response + Timber.d(toLogString(RESPONSE, INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) + Timber.d( + toLogString( + RESPONSE, + INFO, + "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" + ) + ) + it.headers.forEach { header -> + Timber.d(toLogString(RESPONSE, HEADER, header.toString())) + } + Timber.d(toLogString(RESPONSE, BODY, it.body.toString())) + + } + } + } + + companion object { + var httpLogsEnabled: Boolean = false } } From b7fd663d77efab4b529c870e3de18d980a501d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Mon, 5 Oct 2020 14:27:26 +0200 Subject: [PATCH 05/41] Improve http logs --- .../android/lib/common/http/LogBuilder.kt | 15 +++++++--- .../android/lib/common/http/LogInterceptor.kt | 29 +++++-------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index ef9df143..7cf6ef28 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -22,18 +22,25 @@ */ package com.owncloud.android.lib.common.http +import timber.log.Timber +import java.util.Locale + object LogBuilder { - fun toLogString( + fun logHttp( networkPetition: NetworkPetition, networkNode: NetworkNode, description: String - ): String = "[Network, $networkPetition] [$networkNode] $description" + ) = Timber.d("[Network, $networkPetition] [$networkNode] $description") } enum class NetworkPetition { - REQUEST, RESPONSE + REQUEST, RESPONSE; + + override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } enum class NetworkNode { - INFO, HEADER, BODY + INFO, HEADER, BODY; + + override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 400b6120..403b277a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,12 +23,11 @@ */ package com.owncloud.android.lib.common.http -import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.* import com.owncloud.android.lib.common.http.NetworkPetition.* import okhttp3.Interceptor import okhttp3.Response -import timber.log.Timber class LogInterceptor : Interceptor { @@ -39,28 +38,14 @@ class LogInterceptor : Interceptor { return response.also { if (httpLogsEnabled) { // Log request - Timber.d( - toLogString(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - ) - it.headers.forEach { header -> - Timber.d(toLogString(REQUEST, HEADER, header.toString())) - } - Timber.d(toLogString(REQUEST, BODY, it.body.toString())) + logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") + it.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } + logHttp(REQUEST, BODY, it.body.toString()) // Log response - Timber.d(toLogString(RESPONSE, INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) - Timber.d( - toLogString( - RESPONSE, - INFO, - "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" - ) - ) - it.headers.forEach { header -> - Timber.d(toLogString(RESPONSE, HEADER, header.toString())) - } - Timber.d(toLogString(RESPONSE, BODY, it.body.toString())) - + logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") + it.headers.forEach { header -> logHttp(RESPONSE, HEADER, header.toString()) } + logHttp(RESPONSE, BODY, it.body.toString()) } } } From dc3947576064f6c749888cd0136cbedec33a94a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 13 Oct 2020 08:52:04 +0200 Subject: [PATCH 06/41] Add log interceptor disabled by default --- .../com/owncloud/android/lib/common/http/HttpClient.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 9aab751a..574b5539 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -26,7 +26,6 @@ package com.owncloud.android.lib.common.http; import android.content.Context; -import com.owncloud.android.lib.BuildConfig; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.NetworkUtils; import okhttp3.Cookie; @@ -112,6 +111,7 @@ public class HttpClient { }; OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() + .addInterceptor(getLogInterceptor()) .protocols(Arrays.asList(Protocol.HTTP_1_1)) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) @@ -123,11 +123,6 @@ public class HttpClient { // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); - // Http logs enabled only in debug version. TODO: Add an option to enable and disable it. - if (BuildConfig.DEBUG) { - clientBuilder.addInterceptor(getLogInterceptor()); - } - sOkHttpClient = clientBuilder.build(); } catch (Exception e) { From aa665a7295e53468d8e354a22c8c268e2eef55d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 20 Oct 2020 11:31:52 +0200 Subject: [PATCH 07/41] Show request headers and body properly --- .../android/lib/common/http/LogInterceptor.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 403b277a..9aad57a2 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -24,8 +24,11 @@ package com.owncloud.android.lib.common.http import com.owncloud.android.lib.common.http.LogBuilder.logHttp -import com.owncloud.android.lib.common.http.NetworkNode.* -import com.owncloud.android.lib.common.http.NetworkPetition.* +import com.owncloud.android.lib.common.http.NetworkNode.BODY +import com.owncloud.android.lib.common.http.NetworkNode.HEADER +import com.owncloud.android.lib.common.http.NetworkNode.INFO +import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST +import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE import okhttp3.Interceptor import okhttp3.Response @@ -39,8 +42,8 @@ class LogInterceptor : Interceptor { if (httpLogsEnabled) { // Log request logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - it.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } - logHttp(REQUEST, BODY, it.body.toString()) + it.request.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } + logHttp(REQUEST, BODY, it.request.body.toString()) // Log response logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") From c0d2e20bb147f3234de5dd56838229fd38869364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 15:39:48 +0200 Subject: [PATCH 08/41] Log http body if it is not binary --- .../android/lib/common/http/LogBuilder.kt | 3 +- .../android/lib/common/http/LogInterceptor.kt | 132 ++++++++++++++++-- .../owncloud/android/lib/common/http/utf8.kt | 44 ++++++ 3 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index 7cf6ef28..c85f4fd5 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -29,8 +29,9 @@ object LogBuilder { fun logHttp( networkPetition: NetworkPetition, networkNode: NetworkNode, + requestId: String? = "", description: String - ) = Timber.d("[Network, $networkPetition] [$networkNode] $description") + ) = Timber.d("[Network, $networkPetition] [$networkNode] [$requestId] $description") } enum class NetworkPetition { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 9aad57a2..0877deca 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,37 +23,145 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.BODY import com.owncloud.android.lib.common.http.NetworkNode.HEADER import com.owncloud.android.lib.common.http.NetworkNode.INFO import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE +import okhttp3.Headers import okhttp3.Interceptor +import okhttp3.RequestBody import okhttp3.Response +import okhttp3.ResponseBody +import okio.Buffer +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets +import kotlin.math.max class LogInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { - val response = chain.proceed(chain.request()) + if (!httpLogsEnabled) { + return chain.proceed(chain.request()) + } + + val request = chain.request().also { + val requestId = it.headers[OC_X_REQUEST_ID] + logHttp(REQUEST, INFO, requestId, "Type: ${it.method} URL: ${it.url}") + logHeaders(requestId, it.headers, REQUEST) + logRequestBody(requestId, it.body) + } + + val response = chain.proceed(request) return response.also { - if (httpLogsEnabled) { - // Log request - logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - it.request.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } - logHttp(REQUEST, BODY, it.request.body.toString()) - - // Log response - logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") - it.headers.forEach { header -> logHttp(RESPONSE, HEADER, header.toString()) } - logHttp(RESPONSE, BODY, it.body.toString()) - } + val requestId = it.request.headers[OC_X_REQUEST_ID] + logHttp( + RESPONSE, + INFO, + requestId, + "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" + ) + logHeaders(requestId, it.headers, RESPONSE) + logResponseBody(requestId, it.body) } } + private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) { + headers.forEach { header -> + logHttp(networkPetition, HEADER, requestId, "${header.first}: ${header.second}") + } + } + + private fun logRequestBody(requestId: String?, requestBodyParam: RequestBody?) { + requestBodyParam?.let { requestBody -> + + if (requestBody.isOneShot()) { + logHttp(REQUEST, BODY, requestId, "One shot body -- Omitted") + return@let + } + + if (requestBody.isDuplex()) { + logHttp(REQUEST, BODY, requestId, "Duplex body -- Omitted") + return@let + } + + val buffer = Buffer() + requestBody.writeTo(buffer) + + val contentType = requestBody.contentType() + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 + + logHttp(REQUEST, BODY, requestId, "Length: ${requestBody.contentLength()} byte body") + logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}") + logHttp(REQUEST, BODY, requestId, "--> Body start for request") + + if (buffer.isProbablyUtf8()) { + if (requestBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(REQUEST, BODY, requestId, buffer.readString(charset)) + } else { + logHttp(REQUEST, BODY, requestId, buffer.readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Omitted: ${max(0, requestBody.contentLength() - LIMIT_BODY_LOG)} bytes" + ) + } else { + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Binary -- Omitted: ${requestBody.contentLength()} bytes" + ) + } + + } ?: logHttp(REQUEST, BODY, requestId, "Empty body") + } + + private fun logResponseBody(requestId: String?, responseBodyParam: ResponseBody?) { + responseBodyParam?.let { responseBody -> + + val contentType = responseBody.contentType() + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 + + logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body") + logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}") + logHttp(RESPONSE, BODY, requestId, "--> Body start for request") + + val source = responseBody.source() + source.request(LIMIT_BODY_LOG) + val buffer = source.buffer + + if (!buffer.isProbablyUtf8()) { + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" + ) + } + + if (responseBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(charset)) + } else { + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" + ) + } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") + } + companion object { var httpLogsEnabled: Boolean = false + private const val LIMIT_BODY_LOG: Long = 1024 } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt new file mode 100644 index 00000000..9591e425 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.owncloud.android.lib.common.http + +import java.io.EOFException +import okio.Buffer + +/** + * Returns true if the body in question probably contains human readable text. Uses a small + * sample of code points to detect unicode control characters commonly used in binary file + * signatures. + */ +internal fun Buffer.isProbablyUtf8(): Boolean { + try { + val prefix = Buffer() + val byteCount = size.coerceAtMost(64) + copyTo(prefix, 0, byteCount) + for (i in 0 until 16) { + if (prefix.exhausted()) { + break + } + val codePoint = prefix.readUtf8CodePoint() + if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { + return false + } + } + return true + } catch (_: EOFException) { + return false // Truncated UTF-8 sequence. + } +} From 197c86ec64a4b68151ef74154bc6ac28df6584de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 15:59:39 +0200 Subject: [PATCH 09/41] Add LogInterceptor as NetworkInterceptor --- .../java/com/owncloud/android/lib/common/http/HttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 574b5539..06e8056d 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -111,7 +111,7 @@ public class HttpClient { }; OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() - .addInterceptor(getLogInterceptor()) + .addNetworkInterceptor(getLogInterceptor()) .protocols(Arrays.asList(Protocol.HTTP_1_1)) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) From db97ed7fb350182756d18121b038a2f93bbdd2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 18:21:39 +0200 Subject: [PATCH 10/41] Fix response log marked as request one --- .../owncloud/android/lib/common/http/LogInterceptor.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 0877deca..0352b821 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -139,7 +139,7 @@ class LogInterceptor : Interceptor { if (!buffer.isProbablyUtf8()) { logHttp( - REQUEST, + RESPONSE, BODY, requestId, "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" @@ -147,12 +147,12 @@ class LogInterceptor : Interceptor { } if (responseBody.contentLength() < LIMIT_BODY_LOG) { - logHttp(REQUEST, BODY, requestId, buffer.clone().readString(charset)) + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) } else { - logHttp(REQUEST, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) } logHttp( - REQUEST, + RESPONSE, BODY, requestId, "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" From 781f958c9383e2784137630df2d43c02f936e75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Fri, 23 Oct 2020 11:38:40 +0200 Subject: [PATCH 11/41] Do not log chunk request body --- .../owncloud/android/lib/common/network/FileRequestBody.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java index 2df9884d..18746ba7 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java @@ -53,6 +53,11 @@ public class FileRequestBody extends RequestBody implements ProgressiveDataTrans mContentType = contentType; } + @Override + public boolean isOneShot() { + return true; + } + @Override public MediaType contentType() { return mContentType; From 943c5ecb97f3a4a5ee24fb9010b6d8d89fb53931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 27 Oct 2020 16:09:01 +0100 Subject: [PATCH 12/41] Fix typo --- .../com/owncloud/android/lib/common/http/LogInterceptor.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 0352b821..30860f54 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -131,7 +131,7 @@ class LogInterceptor : Interceptor { logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body") logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}") - logHttp(RESPONSE, BODY, requestId, "--> Body start for request") + logHttp(RESPONSE, BODY, requestId, "--> Body start for response") val source = responseBody.source() source.request(LIMIT_BODY_LOG) @@ -142,7 +142,7 @@ class LogInterceptor : Interceptor { RESPONSE, BODY, requestId, - "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" + "<-- Body end for response -- Binary -- Omitted: ${responseBody.contentLength()} bytes" ) } @@ -155,7 +155,7 @@ class LogInterceptor : Interceptor { RESPONSE, BODY, requestId, - "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" + "<-- Body end for response -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" ) } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") } From 460f85f2e175879894898f595be75a5d9588cff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 27 Oct 2020 16:12:23 +0100 Subject: [PATCH 13/41] Remove binary file logs --- .../lib/common/network/ChunkFromFileRequestBody.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java index 53abaf9a..40f168ea 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java @@ -84,18 +84,12 @@ public class ChunkFromFileRequestBody extends FileRequestBody { long maxCount = Math.min(mOffset + mChunkSize, mChannel.size()); while (mChannel.position() < maxCount) { - Timber.v("Sink buffer size: %s", sink.buffer().size()); - readCount = mChannel.read(mBuffer); - Timber.v("Read " + readCount + " bytes from file channel to " + mBuffer.toString()); - - sink.buffer().write(mBuffer.array(), 0, readCount); + sink.getBuffer().write(mBuffer.array(), 0, readCount); sink.flush(); - Timber.v("Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size()); - mBuffer.clear(); if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks mTransferred += readCount; From 5e86e9f0e4cb7ae49a97e33a4461aaaad54b1c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 28 Oct 2020 09:04:17 +0100 Subject: [PATCH 14/41] Determine if a body is loggable based on its content-type --- .../lib/common/http/HttpConstants.java | 8 ++++ .../android/lib/common/http/LogBuilder.kt | 18 ++++++++ .../android/lib/common/http/LogInterceptor.kt | 34 ++++++++------ .../owncloud/android/lib/common/http/utf8.kt | 44 ------------------- 4 files changed, 46 insertions(+), 58 deletions(-) delete mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java index 3850cd3f..b86534a3 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java @@ -51,6 +51,14 @@ public class HttpConstants { public static final String ACCEPT_ENCODING_IDENTITY = "identity"; public static final String OC_FILE_REMOTE_ID = "OC-FileId"; + /*********************************************************************************************************** + ************************************************ CONTENT TYPES ******************************************** + ***********************************************************************************************************/ + + public static final String CONTENT_TYPE_XML = "application/xml"; + public static final String CONTENT_TYPE_JSON = "application/json"; + public static final String CONTENT_TYPE_WWW_FORM = "application/x-www-form-urlencoded"; + /*********************************************************************************************************** ************************************************ STATUS CODES ********************************************* ***********************************************************************************************************/ diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index c85f4fd5..c0ca4fb0 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -22,6 +22,10 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_JSON +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_WWW_FORM +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_XML +import okhttp3.MediaType import timber.log.Timber import java.util.Locale @@ -45,3 +49,17 @@ enum class NetworkNode { override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } + +/** + * Check whether a media type is loggable. + * + * @return true if its type is text, xml, json, or x-www-form-urlencoded. + */ +fun MediaType?.isLoggable(): Boolean = + this?.let { mediaType -> + val mediaTypeString = mediaType.toString() + (mediaType.type == "text" || + mediaTypeString.contains(CONTENT_TYPE_XML) || + mediaTypeString.contains(CONTENT_TYPE_JSON) || + mediaTypeString.contains(CONTENT_TYPE_WWW_FORM)) + } ?: false diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 30860f54..a6f5dd74 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -99,7 +99,7 @@ class LogInterceptor : Interceptor { logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}") logHttp(REQUEST, BODY, requestId, "--> Body start for request") - if (buffer.isProbablyUtf8()) { + if (contentType.isLoggable()) { if (requestBody.contentLength() < LIMIT_BODY_LOG) { logHttp(REQUEST, BODY, requestId, buffer.readString(charset)) } else { @@ -137,7 +137,25 @@ class LogInterceptor : Interceptor { source.request(LIMIT_BODY_LOG) val buffer = source.buffer - if (!buffer.isProbablyUtf8()) { + if (contentType.isLoggable()) { + + if (responseBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) + } else { + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + RESPONSE, + BODY, + requestId, + "<-- Body end for response -- Omitted: ${ + max( + 0, + responseBody.contentLength() - LIMIT_BODY_LOG + ) + } bytes" + ) + } else { logHttp( RESPONSE, BODY, @@ -145,18 +163,6 @@ class LogInterceptor : Interceptor { "<-- Body end for response -- Binary -- Omitted: ${responseBody.contentLength()} bytes" ) } - - if (responseBody.contentLength() < LIMIT_BODY_LOG) { - logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) - } else { - logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) - } - logHttp( - RESPONSE, - BODY, - requestId, - "<-- Body end for response -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" - ) } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt deleted file mode 100644 index 9591e425..00000000 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2015 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.owncloud.android.lib.common.http - -import java.io.EOFException -import okio.Buffer - -/** - * Returns true if the body in question probably contains human readable text. Uses a small - * sample of code points to detect unicode control characters commonly used in binary file - * signatures. - */ -internal fun Buffer.isProbablyUtf8(): Boolean { - try { - val prefix = Buffer() - val byteCount = size.coerceAtMost(64) - copyTo(prefix, 0, byteCount) - for (i in 0 until 16) { - if (prefix.exhausted()) { - break - } - val codePoint = prefix.readUtf8CodePoint() - if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { - return false - } - } - return true - } catch (_: EOFException) { - return false // Truncated UTF-8 sequence. - } -} From 2b64b83b8939c01fd5aa3e9b34626b1a87d4c8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 28 Oct 2020 09:17:27 +0100 Subject: [PATCH 15/41] Do not log Authorization header --- .../owncloud/android/lib/common/http/LogInterceptor.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index a6f5dd74..0ca90a47 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,6 +23,7 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.AUTHORIZATION_HEADER import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.BODY @@ -72,7 +73,12 @@ class LogInterceptor : Interceptor { private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) { headers.forEach { header -> - logHttp(networkPetition, HEADER, requestId, "${header.first}: ${header.second}") + val headerValue: String = if (header.first.equals(AUTHORIZATION_HEADER, true)) { + "[redacted]" + } else { + header.second + } + logHttp(networkPetition, HEADER, requestId, "${header.first}: $headerValue") } } From 8a042314736b37a1d143dbb7f6e92d7f205254cb Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 6 Oct 2020 14:24:15 +0200 Subject: [PATCH 16/41] move responses models into module folder --- .../lib/resources/status/GetRemoteCapabilitiesOperation.kt | 4 ++-- .../{response => status/responses}/CapabilityResponse.kt | 2 +- .../{response => status/responses}/CommonOcsResponse.kt | 2 +- .../android/lib/resources/users/GetRemoteUserInfoOperation.kt | 4 ++-- .../{response => users/responses}/UserInfoResponse.kt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/{response => status/responses}/CapabilityResponse.kt (99%) rename owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/{response => status/responses}/CommonOcsResponse.kt (96%) rename owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/{response => users/responses}/UserInfoResponse.kt (96%) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt index f9f164eb..3117494b 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt @@ -34,8 +34,8 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK -import com.owncloud.android.lib.resources.response.CapabilityResponse -import com.owncloud.android.lib.resources.response.CommonOcsResponse +import com.owncloud.android.lib.resources.status.responses.CapabilityResponse +import com.owncloud.android.lib.resources.status.responses.CommonOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CapabilityResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt similarity index 99% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CapabilityResponse.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt index 49efaea9..dea2431e 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CapabilityResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt @@ -22,7 +22,7 @@ * THE SOFTWARE. * */ -package com.owncloud.android.lib.resources.response +package com.owncloud.android.lib.resources.status.responses import com.owncloud.android.lib.resources.status.RemoteCapability import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBooleanType diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CommonOcsResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt similarity index 96% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CommonOcsResponse.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt index d8402eb9..491db0d1 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/CommonOcsResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.owncloud.android.lib.resources.response +package com.owncloud.android.lib.resources.status.responses import com.squareup.moshi.JsonClass diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt index 53600d29..07e6c95c 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt @@ -29,8 +29,8 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode -import com.owncloud.android.lib.resources.response.CommonOcsResponse -import com.owncloud.android.lib.resources.response.UserInfoResponse +import com.owncloud.android.lib.resources.status.responses.CommonOcsResponse +import com.owncloud.android.lib.resources.users.responses.UserInfoResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/UserInfoResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/responses/UserInfoResponse.kt similarity index 96% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/UserInfoResponse.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/responses/UserInfoResponse.kt index 1ff3b94e..0371e50f 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/response/UserInfoResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/responses/UserInfoResponse.kt @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.owncloud.android.lib.resources.response +package com.owncloud.android.lib.resources.users.responses import com.owncloud.android.lib.resources.users.RemoteUserInfo import com.squareup.moshi.Json From 4f72f93f8b7af0661fe3682b3e2bf62ff48a244e Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 6 Oct 2020 15:30:24 +0200 Subject: [PATCH 17/41] clean run method by braking down into small functions --- .../shares/GetRemoteShareesOperation.kt | 140 ++++++++++-------- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index e3432b5b..8033de0a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -28,12 +28,14 @@ package com.owncloud.android.lib.resources.shares +import android.net.Uri import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.http.HttpConstants import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK +import org.json.JSONArray import org.json.JSONObject import timber.log.Timber import java.net.URL @@ -80,78 +82,94 @@ class GetRemoteShareesOperation (private val searchString: String, private val page: Int, private val perPage: Int) : RemoteOperation>() { + private fun buildRequestUri(baseUri: Uri) = + baseUri.buildUpon() + .appendEncodedPath(OCS_ROUTE) + .appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT) + .appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE) + .appendQueryParameter(PARAM_SEARCH, searchString) + .appendQueryParameter(PARAM_PAGE, page.toString()) + .appendQueryParameter(PARAM_PER_PAGE, perPage.toString()) + .build() + + private fun parseResponse(response: String): Array { + val respJSON = JSONObject(response) + val respOCS = respJSON.getJSONObject(NODE_OCS) + val respData = respOCS.getJSONObject(NODE_DATA) + val respExact = respData.getJSONObject(NODE_EXACT) + val respExactUsers = respExact.getJSONArray(NODE_USERS) + val respExactGroups = respExact.getJSONArray(NODE_GROUPS) + val respExactRemotes = respExact.getJSONArray(NODE_REMOTES) + val respPartialUsers = respData.getJSONArray(NODE_USERS) + val respPartialGroups = respData.getJSONArray(NODE_GROUPS) + val respPartialRemotes = respData.getJSONArray(NODE_REMOTES) + return arrayOf( + respExactUsers, + respExactGroups, + respExactRemotes, + respPartialUsers, + respPartialGroups, + respPartialRemotes + ) + } + + private fun onResultUnsuccessful( + method: GetMethod, + response: String?, + status: Int + ): RemoteOperationResult> { + Timber.e("Failed response while getting users/groups from the server ") + if (response != null) { + Timber.e("*** status code: $status; response message: $response") + } else { + Timber.e("*** status code: $status") + } + return RemoteOperationResult(method) + } + + private fun flattenResultData(jsonResults: Array):ArrayList { + val data = ArrayList() // For result data + for (i in 0..jsonResults.size) { + for (j in 0 until jsonResults[i].length()) { + val jsonResult = jsonResults[i].getJSONObject(j) + data.add(jsonResult) + Timber.d("*** Added item: ${jsonResult.getString(PROPERTY_LABEL)}") + } + } + return data + } + + private fun onRequestSuccessful(response: String?): RemoteOperationResult> { + Timber.d("Successful response: $response") + + // Parse the response + val jsonResults = parseResponse(response!!) + + Timber.d("*** Get Users or groups completed ") + val result = RemoteOperationResult>(OK) + result.data = flattenResultData(jsonResults) + return result + } + override fun run(client: OwnCloudClient): RemoteOperationResult> { - var result: RemoteOperationResult> + val requestUri = buildRequestUri(client.baseUri) - try { - val requestUri = client.baseUri - val uriBuilder = requestUri.buildUpon() - .appendEncodedPath(OCS_ROUTE) - .appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT) - .appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE) - .appendQueryParameter(PARAM_SEARCH, searchString) - .appendQueryParameter(PARAM_PAGE, page.toString()) - .appendQueryParameter(PARAM_PER_PAGE, perPage.toString()) - - val getMethod = GetMethod(URL(uriBuilder.build().toString())) - - getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + val getMethod = GetMethod(URL(requestUri.toString())) + getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + return try { val status = client.executeHttpMethod(getMethod) val response = getMethod.getResponseBodyAsString() - if (isSuccess(status)) { - Timber.d("Successful response: $response") - - // Parse the response - val respJSON = JSONObject(response) - val respOCS = respJSON.getJSONObject(NODE_OCS) - val respData = respOCS.getJSONObject(NODE_DATA) - val respExact = respData.getJSONObject(NODE_EXACT) - val respExactUsers = respExact.getJSONArray(NODE_USERS) - val respExactGroups = respExact.getJSONArray(NODE_GROUPS) - val respExactRemotes = respExact.getJSONArray(NODE_REMOTES) - val respPartialUsers = respData.getJSONArray(NODE_USERS) - val respPartialGroups = respData.getJSONArray(NODE_GROUPS) - val respPartialRemotes = respData.getJSONArray(NODE_REMOTES) - val jsonResults = arrayOf( - respExactUsers, - respExactGroups, - respExactRemotes, - respPartialUsers, - respPartialGroups, - respPartialRemotes - ) - - val data = ArrayList() // For result data - for (i in 0..5) { - for (j in 0 until jsonResults[i].length()) { - val jsonResult = jsonResults[i].getJSONObject(j) - data.add(jsonResult) - Timber.d("*** Added item: ${jsonResult.getString(PROPERTY_LABEL)}") - } - } - - result = RemoteOperationResult(OK) - result.data = data - - Timber.d("*** Get Users or groups completed ") - + if (!isSuccess(status)) { + onResultUnsuccessful(getMethod, response, status) } else { - result = RemoteOperationResult(getMethod) - Timber.e("Failed response while getting users/groups from the server ") - if (response != null) { - Timber.e("*** status code: $status; response message: $response") - } else { - Timber.e("*** status code: $status") - } + onRequestSuccessful(response) } } catch (e: Exception) { - result = RemoteOperationResult(e) Timber.e(e, "Exception while getting users/groups") + RemoteOperationResult(e) } - - return result } private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK From 9f1c20b418f416e449318f4c89d35f41b1b36e83 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 8 Oct 2020 15:17:28 +0200 Subject: [PATCH 18/41] add Sharee response model --- .../responses => }/CommonOcsResponse.kt | 2 +- .../shares/responses/ShareeResponse.kt | 91 +++++++++++++++++++ .../status/GetRemoteCapabilitiesOperation.kt | 2 +- .../users/GetRemoteUserInfoOperation.kt | 2 +- 4 files changed, 94 insertions(+), 3 deletions(-) rename owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/{status/responses => }/CommonOcsResponse.kt (96%) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt similarity index 96% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt index 491db0d1..2cfbe2ed 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CommonOcsResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt @@ -21,7 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.owncloud.android.lib.resources.status.responses +package com.owncloud.android.lib.resources import com.squareup.moshi.JsonClass diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt new file mode 100644 index 00000000..19f19728 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -0,0 +1,91 @@ +/* ownCloud Android Library is available under MIT license + * + * Copyright (C) 2020 ownCloud 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.shares.responses + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * This was modeled according to the documentation: + * https://doc.owncloud.com/server/developer_manual/core/apis/ocs-recipient-api.html#get-shares-recipients + */ +@JsonClass(generateAdapter = true) +data class ShareeOcsResponse( + @Json(name = "data") + val data: ShareeResponseData?, + @Json(name = "meta") + val meta: ShareeMeta? +) + +@JsonClass(generateAdapter = true) +data class ShareeResponseData( + @Json(name = "exact") + val exact: ExactSharees?, + @Json(name = "groups") + val groups: List?, + @Json(name = "remotes") + val remotes: List?, + @Json(name = "users") + val users: List? +) + +@JsonClass(generateAdapter = true) +data class ExactSharees( + @Json(name = "groups") + val groups: List?, + @Json(name = "remotes") + val remotes: List?, + @Json(name = "users") + val users: List? +) + +@JsonClass(generateAdapter = true) +data class ShareeItem( + @Json(name = "label") + val label: String?, + @Json(name = "value") + val value: ShareeValue? +) + +@JsonClass(generateAdapter = true) +data class ShareeValue( + @Json(name = "shareType") + val shareType: Int?, + @Json(name = "shareWith") + val shareWith: String? +) + +@JsonClass(generateAdapter = true) +data class ShareeMeta( + @Json(name = "itemsperpage") + val itemsPerPage: Int?, + @Json(name = "message") + val message: String?, + @Json(name = "status") + val status: String?, + @Json(name = "statuscode") + val statusCode: Int?, + @Json(name = "totalitems") + val totalItems: Int? +) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt index 3117494b..806440be 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteCapabilitiesOperation.kt @@ -35,7 +35,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK import com.owncloud.android.lib.resources.status.responses.CapabilityResponse -import com.owncloud.android.lib.resources.status.responses.CommonOcsResponse +import com.owncloud.android.lib.resources.CommonOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt index 07e6c95c..d1f2a43c 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt @@ -29,7 +29,7 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode -import com.owncloud.android.lib.resources.status.responses.CommonOcsResponse +import com.owncloud.android.lib.resources.CommonOcsResponse import com.owncloud.android.lib.resources.users.responses.UserInfoResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi From 6bdb2badca6b5f6a7e5419f4abc91e4690a43176 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 24 Sep 2020 12:27:25 +0200 Subject: [PATCH 19/41] add support for tests --- gradle.properties | 3 ++- owncloudComLibrary/build.gradle | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 946d709d..5c0bd337 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ android.enableJetifier=true android.useAndroidX=true -org.gradle.jvmargs=-Xmx1536M \ No newline at end of file +org.gradle.jvmargs=-Xmx1536M +android.enableUnitTestBinaryResources=true diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 6db1f790..2ac7adea 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -14,6 +14,14 @@ dependencies { exclude module: "kotlin-reflect" } kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" + + testImplementation 'junit:junit:4.13' + testImplementation 'org.robolectric:robolectric:4.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test:core:1.3.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test:rules:1.3.0' } android { @@ -40,4 +48,10 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + testOptions { + unitTests { + includeAndroidResources = true + } + } } From 1c08a942d116c3ada6c41019f9b212c6a6c5ef80 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 8 Oct 2020 15:57:03 +0200 Subject: [PATCH 20/41] test model --- .../lib/resources/CommonOcsResponse.kt | 10 +- .../shares/responses/ShareeResponse.kt | 22 --- .../android/lib/ShareeResponseTest.kt | 134 ++++++++++++++++++ 3 files changed, 142 insertions(+), 24 deletions(-) create mode 100644 owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt index 2cfbe2ed..7a37dc82 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt @@ -23,6 +23,7 @@ */ package com.owncloud.android.lib.resources +import com.squareup.moshi.Json import com.squareup.moshi.JsonClass // Response retrieved by OCS Rest API, used to obtain capabilities, shares and user info among others. @@ -41,6 +42,11 @@ data class OCSResponse( @JsonClass(generateAdapter = true) data class MetaData( val status: String, - val statuscode: Int, - val message: String? + @Json(name = "statuscode") + val statusCode: Int, + val message: String?, + @Json(name = "itemsperpage") + val itemsPerPage: String?, + @Json(name = "totalitems") + val totalItems: String? ) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index 19f19728..fe3ed67c 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -32,14 +32,6 @@ import com.squareup.moshi.JsonClass */ @JsonClass(generateAdapter = true) data class ShareeOcsResponse( - @Json(name = "data") - val data: ShareeResponseData?, - @Json(name = "meta") - val meta: ShareeMeta? -) - -@JsonClass(generateAdapter = true) -data class ShareeResponseData( @Json(name = "exact") val exact: ExactSharees?, @Json(name = "groups") @@ -75,17 +67,3 @@ data class ShareeValue( @Json(name = "shareWith") val shareWith: String? ) - -@JsonClass(generateAdapter = true) -data class ShareeMeta( - @Json(name = "itemsperpage") - val itemsPerPage: Int?, - @Json(name = "message") - val message: String?, - @Json(name = "status") - val status: String?, - @Json(name = "statuscode") - val statusCode: Int?, - @Json(name = "totalitems") - val totalItems: Int? -) diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt new file mode 100644 index 00000000..4248018a --- /dev/null +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt @@ -0,0 +1,134 @@ +package com.owncloud.android.lib + +import com.owncloud.android.lib.resources.CommonOcsResponse +import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import junit.framework.Assert.assertEquals +import junit.framework.Assert.assertTrue +import org.junit.Assert.assertNotEquals +import org.junit.Before +import org.junit.Test +import java.lang.reflect.Type + +class ShareeResponseTest { + + var response: CommonOcsResponse? = null + + @Before + fun prepare() { + val moshi = Moshi.Builder().build() + val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + response = adapter.fromJson(EXAMPLE_RESPONSE) + } + + @Test + fun `check structure - ok - contains meta`() { + assertEquals("OK", response?.ocs?.meta?.message!!) + assertEquals(200, response?.ocs?.meta?.statusCode!!) + assertEquals("ok", response?.ocs?.meta?.status!!) + assertTrue(response?.ocs?.meta?.itemsPerPage?.isEmpty()!!) + assertTrue(response?.ocs?.meta?.totalItems?.isEmpty()!!) + } + + @Test + fun `check structure - ok - contains exact`() { + assertNotEquals(null, response?.ocs?.data?.exact) + } + + @Test + fun `check structure - ok - contains groups`() { + assertNotEquals(null, response?.ocs?.data?.groups) + } + + @Test + fun `check structure - ok - contains remotes`() { + assertNotEquals(null, response?.ocs?.data?.remotes) + } + + @Test + fun `check structure - ok - contains users`() { + assertNotEquals(null, response?.ocs?.data?.users) + } + + @Test + fun `check structure - ok - groups contains two items`() { + assertEquals(2, response?.ocs?.data?.groups?.size) + } + + @Test + fun `check structure - ok - users contains two items`() { + assertEquals(2, response?.ocs?.data?.users?.size) + } + + @Test + fun `check structure - ok - exact_users contains one item`() { + assertEquals(1, response?.ocs?.data?.exact?.users?.size) + } + + companion object { + val EXAMPLE_RESPONSE = """ +{ + "ocs": { + "data": { + "exact": { + "groups": [], + "remotes": [], + "users": [ + { + "label": "admin", + "value": { + "shareType": 0, + "shareWith": "admin" + } + } + ] + }, + "groups": [ + { + "label": "group1", + "value": { + "shareType": 1, + "shareWith": "group1" + } + }, + { + "label": "group2", + "value": { + "shareType": 1, + "shareWith": "group2" + } + } + ], + "remotes": [], + "users": [ + { + "label": "user1", + "value": { + "shareType": 0, + "shareWith": "user1" + } + }, + { + "label": "user2", + "value": { + "shareType": 0, + "shareWith": "user2" + } + } + ] + }, + "meta": { + "itemsperpage": "", + "message": "OK", + "status": "ok", + "statuscode": 200, + "totalitems": "" + } + } +} + """ + } +} \ No newline at end of file From b86638412efe3e75cccd8bb6e3b02c31276ef375 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 8 Oct 2020 16:10:20 +0200 Subject: [PATCH 21/41] update GetRemoteShareesOperation to use moshi --- .../shares/GetRemoteShareesOperation.kt | 52 ++++++------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index 8033de0a..b91e4ef8 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -35,9 +35,15 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK +import com.owncloud.android.lib.resources.CommonOcsResponse +import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types import org.json.JSONArray import org.json.JSONObject import timber.log.Timber +import java.lang.reflect.Type import java.net.URL import java.util.ArrayList @@ -80,7 +86,7 @@ class GetRemoteShareesOperation * @param perPage maximum number of results in a single page */ (private val searchString: String, private val page: Int, private val perPage: Int) : - RemoteOperation>() { + RemoteOperation() { private fun buildRequestUri(baseUri: Uri) = baseUri.buildUpon() @@ -92,32 +98,18 @@ class GetRemoteShareesOperation .appendQueryParameter(PARAM_PER_PAGE, perPage.toString()) .build() - private fun parseResponse(response: String): Array { - val respJSON = JSONObject(response) - val respOCS = respJSON.getJSONObject(NODE_OCS) - val respData = respOCS.getJSONObject(NODE_DATA) - val respExact = respData.getJSONObject(NODE_EXACT) - val respExactUsers = respExact.getJSONArray(NODE_USERS) - val respExactGroups = respExact.getJSONArray(NODE_GROUPS) - val respExactRemotes = respExact.getJSONArray(NODE_REMOTES) - val respPartialUsers = respData.getJSONArray(NODE_USERS) - val respPartialGroups = respData.getJSONArray(NODE_GROUPS) - val respPartialRemotes = respData.getJSONArray(NODE_REMOTES) - return arrayOf( - respExactUsers, - respExactGroups, - respExactRemotes, - respPartialUsers, - respPartialGroups, - respPartialRemotes - ) + private fun parseResponse(response: String): ShareeOcsResponse? { + val moshi = Moshi.Builder().build() + val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + return adapter.fromJson(response)!!.ocs.data } private fun onResultUnsuccessful( method: GetMethod, response: String?, status: Int - ): RemoteOperationResult> { + ): RemoteOperationResult { Timber.e("Failed response while getting users/groups from the server ") if (response != null) { Timber.e("*** status code: $status; response message: $response") @@ -139,19 +131,15 @@ class GetRemoteShareesOperation return data } - private fun onRequestSuccessful(response: String?): RemoteOperationResult> { + private fun onRequestSuccessful(response: String?): RemoteOperationResult { + val result = RemoteOperationResult(OK) Timber.d("Successful response: $response") - - // Parse the response - val jsonResults = parseResponse(response!!) - + result.data = parseResponse(response!!) Timber.d("*** Get Users or groups completed ") - val result = RemoteOperationResult>(OK) - result.data = flattenResultData(jsonResults) return result } - override fun run(client: OwnCloudClient): RemoteOperationResult> { + override fun run(client: OwnCloudClient): RemoteOperationResult { val requestUri = buildRequestUri(client.baseUri) val getMethod = GetMethod(URL(requestUri.toString())) @@ -191,12 +179,6 @@ class GetRemoteShareesOperation private const val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups // JSON Node names - private const val NODE_OCS = "ocs" - private const val NODE_DATA = "data" - private const val NODE_EXACT = "exact" - private const val NODE_USERS = "users" - private const val NODE_GROUPS = "groups" - private const val NODE_REMOTES = "remotes" const val NODE_VALUE = "value" const val PROPERTY_LABEL = "label" const val PROPERTY_SHARE_TYPE = "shareType" From fe425c80836ad8bf34734108ecf3926871c7b380 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 13 Oct 2020 11:05:53 +0200 Subject: [PATCH 22/41] update shareeservice to use ShareeOcsResponse --- .../lib/resources/shares/GetRemoteShareesOperation.kt | 2 ++ .../android/lib/resources/shares/services/ShareeService.kt | 6 +++--- .../shares/services/implementation/OCShareeService.kt | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index b91e4ef8..6fb57223 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -1,5 +1,6 @@ /* ownCloud Android Library is available under MIT license * + * @author Christian Schabesberger * @author masensio * @author David A. Velasco * @author David González Verdugo @@ -73,6 +74,7 @@ import java.util.ArrayList * Status codes: * 100 - successful * + * @author Christian Schabesberger * @author masensio * @author David A. Velasco * @author David González Verdugo diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt index ab6d9e83..95983ec5 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt @@ -1,6 +1,7 @@ /** * ownCloud Android client application * + * @author Christian Schabesberger * @author David González Verdugo * * Copyright (C) 2020 ownCloud GmbH. @@ -22,13 +23,12 @@ package com.owncloud.android.lib.resources.shares.services import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.Service -import org.json.JSONObject -import java.util.ArrayList +import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse interface ShareeService : Service { fun getSharees( searchString: String, page: Int, perPage: Int - ): RemoteOperationResult> + ): RemoteOperationResult } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt index 370ef34b..1ba7e0cb 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt @@ -23,6 +23,7 @@ package com.owncloud.android.lib.resources.shares.services.implementation import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation +import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse import com.owncloud.android.lib.resources.shares.services.ShareeService import org.json.JSONObject import java.util.ArrayList @@ -33,7 +34,7 @@ class OCShareeService(override val client: OwnCloudClient) : searchString: String, page: Int, perPage: Int - ): RemoteOperationResult> = + ): RemoteOperationResult = GetRemoteShareesOperation( searchString, page, From 7402c89a18ae8f08401ffa5d9b65d98c4c178f8d Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 13 Oct 2020 11:21:37 +0200 Subject: [PATCH 23/41] get flat representation from ShareeOcsResponse --- .../shares/responses/ShareeResponse.kt | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index fe3ed67c..ab779eac 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -40,7 +40,23 @@ data class ShareeOcsResponse( val remotes: List?, @Json(name = "users") val users: List? -) +) { + fun getFlatRepresentation() + = ArrayList().apply { + if(exact != null) { + addAll(exact.getFlatRepresentation()) + } + if(users != null) { + addAll(users) + } + if(remotes != null) { + addAll(remotes) + } + if(groups != null) { + addAll(groups) + } + } +} @JsonClass(generateAdapter = true) data class ExactSharees( @@ -50,7 +66,20 @@ data class ExactSharees( val remotes: List?, @Json(name = "users") val users: List? -) +) { + fun getFlatRepresentation() + = ArrayList().apply { + if(users != null) { + addAll(users) + } + if(remotes != null) { + addAll(remotes) + } + if(groups != null) { + addAll(groups) + } + } +} @JsonClass(generateAdapter = true) data class ShareeItem( From 26def4fbe254f7297de891d27a5c56049f4f9b28 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 13 Oct 2020 14:25:15 +0200 Subject: [PATCH 24/41] return sharees without exact match --- .../android/lib/resources/shares/responses/ShareeResponse.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index ab779eac..b084b206 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -41,11 +41,8 @@ data class ShareeOcsResponse( @Json(name = "users") val users: List? ) { - fun getFlatRepresentation() + fun getFlatRepresentationWithoutExact() = ArrayList().apply { - if(exact != null) { - addAll(exact.getFlatRepresentation()) - } if(users != null) { addAll(users) } From 90b6ff52f2b175c461964a2e0103bc6122cce04c Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 13 Oct 2020 14:44:15 +0200 Subject: [PATCH 25/41] add aditional data field to ocs sharees --- .../resources/shares/responses/ShareeResponse.kt | 4 +++- .../com/owncloud/android/lib/ShareeResponseTest.kt | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index b084b206..ca7b8e67 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -91,5 +91,7 @@ data class ShareeValue( @Json(name = "shareType") val shareType: Int?, @Json(name = "shareWith") - val shareWith: String? + val shareWith: String?, + @Json(name ="shareWithAdditionalInfo") + val additionalInfo: String? ) diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt index 4248018a..a1646b67 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt @@ -68,6 +68,16 @@ class ShareeResponseTest { assertEquals(1, response?.ocs?.data?.exact?.users?.size) } + @Test + fun `check structure - ok - user1 contains additional data`() { + assertEquals("user1@user1.com", response?.ocs?.data?.users?.get(0)?.value?.additionalInfo) + } + + @Test + fun `check structure - ok - user2 does not contain additional data`() { + assertEquals(null, response!!.ocs.data.users!![1].value!!.additionalInfo) + } + companion object { val EXAMPLE_RESPONSE = """ { @@ -108,7 +118,8 @@ class ShareeResponseTest { "label": "user1", "value": { "shareType": 0, - "shareWith": "user1" + "shareWith": "user1", + "shareWithAdditionalInfo": "user1@user1.com" } }, { From 34bf83df30cc4311dfcfe0e6440ce4399db4384b Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 13 Oct 2020 15:23:59 +0200 Subject: [PATCH 26/41] make sharee parts non null that can't be null --- .../shares/responses/ShareeResponse.kt | 52 +++++++------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index ca7b8e67..f372747e 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -35,63 +35,49 @@ data class ShareeOcsResponse( @Json(name = "exact") val exact: ExactSharees?, @Json(name = "groups") - val groups: List?, + val groups: List, @Json(name = "remotes") - val remotes: List?, + val remotes: List, @Json(name = "users") - val users: List? + val users: List ) { - fun getFlatRepresentationWithoutExact() - = ArrayList().apply { - if(users != null) { - addAll(users) - } - if(remotes != null) { - addAll(remotes) - } - if(groups != null) { - addAll(groups) - } + fun getFlatRepresentationWithoutExact() = ArrayList().apply { + addAll(users) + addAll(remotes) + addAll(groups) } } @JsonClass(generateAdapter = true) data class ExactSharees( @Json(name = "groups") - val groups: List?, + val groups: List, @Json(name = "remotes") - val remotes: List?, + val remotes: List, @Json(name = "users") - val users: List? + val users: List ) { - fun getFlatRepresentation() - = ArrayList().apply { - if(users != null) { - addAll(users) - } - if(remotes != null) { - addAll(remotes) - } - if(groups != null) { - addAll(groups) - } + fun getFlatRepresentation() = ArrayList().apply { + addAll(users) + addAll(remotes) + addAll(groups) } } @JsonClass(generateAdapter = true) data class ShareeItem( @Json(name = "label") - val label: String?, + val label: String, @Json(name = "value") - val value: ShareeValue? + val value: ShareeValue ) @JsonClass(generateAdapter = true) data class ShareeValue( @Json(name = "shareType") - val shareType: Int?, + val shareType: Int, @Json(name = "shareWith") - val shareWith: String?, - @Json(name ="shareWithAdditionalInfo") + val shareWith: String, + @Json(name = "shareWithAdditionalInfo") val additionalInfo: String? ) From 29de5aba34267439806c6a445d6db00cac4123ec Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Wed, 14 Oct 2020 11:11:46 +0200 Subject: [PATCH 27/41] disable unitTestBinaryResource as its deprecated --- gradle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5c0bd337..53ae0ae4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,3 @@ android.enableJetifier=true android.useAndroidX=true org.gradle.jvmargs=-Xmx1536M -android.enableUnitTestBinaryResources=true From db478efedc6c9725c49d69cfdbc1be9ee204080f Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Wed, 14 Oct 2020 13:04:03 +0200 Subject: [PATCH 28/41] refactor ShareType --- .../android/lib/resources/shares/RemoteShare.kt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt index 20bb1ae9..ac33ff81 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt @@ -106,17 +106,7 @@ enum class ShareType constructor(val value: Int) { FEDERATED(6); companion object { - fun fromValue(value: Int): ShareType? { - return when (value) { - -1 -> UNKNOWN - 0 -> USER - 1 -> GROUP - 3 -> PUBLIC_LINK - 4 -> EMAIL - 5 -> CONTACT - 6 -> FEDERATED - else -> null - } - } + private val values = values(); + fun fromValue(value: Int) = values.firstOrNull { it.value == value } } } From 76c55c9a9c6c140a156f0ba0184a8dda3ed52586 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Mon, 19 Oct 2020 15:10:41 +0200 Subject: [PATCH 29/41] add changes according to review --- owncloudComLibrary/build.gradle | 12 ------- .../shares/GetRemoteShareesOperation.kt | 12 ------- .../shares/responses/ShareeResponse.kt | 11 ------- .../shares/responses}/ShareeResponseTest.kt | 31 ++++++++++++++++--- 4 files changed, 27 insertions(+), 39 deletions(-) rename owncloudComLibrary/src/test/java/com/owncloud/android/lib/{ => resources/shares/responses}/ShareeResponseTest.kt (75%) diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 2ac7adea..5537f94e 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -16,12 +16,6 @@ dependencies { kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" testImplementation 'junit:junit:4.13' - testImplementation 'org.robolectric:robolectric:4.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - androidTestImplementation 'androidx.test:runner:1.3.0' - androidTestImplementation 'androidx.test:core:1.3.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test:rules:1.3.0' } android { @@ -48,10 +42,4 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - - testOptions { - unitTests { - includeAndroidResources = true - } - } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index 6fb57223..91271f0a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -121,18 +121,6 @@ class GetRemoteShareesOperation return RemoteOperationResult(method) } - private fun flattenResultData(jsonResults: Array):ArrayList { - val data = ArrayList() // For result data - for (i in 0..jsonResults.size) { - for (j in 0 until jsonResults[i].length()) { - val jsonResult = jsonResults[i].getJSONObject(j) - data.add(jsonResult) - Timber.d("*** Added item: ${jsonResult.getString(PROPERTY_LABEL)}") - } - } - return data - } - private fun onRequestSuccessful(response: String?): RemoteOperationResult { val result = RemoteOperationResult(OK) Timber.d("Successful response: $response") diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt index f372747e..0cd0162a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponse.kt @@ -32,13 +32,9 @@ import com.squareup.moshi.JsonClass */ @JsonClass(generateAdapter = true) data class ShareeOcsResponse( - @Json(name = "exact") val exact: ExactSharees?, - @Json(name = "groups") val groups: List, - @Json(name = "remotes") val remotes: List, - @Json(name = "users") val users: List ) { fun getFlatRepresentationWithoutExact() = ArrayList().apply { @@ -50,11 +46,8 @@ data class ShareeOcsResponse( @JsonClass(generateAdapter = true) data class ExactSharees( - @Json(name = "groups") val groups: List, - @Json(name = "remotes") val remotes: List, - @Json(name = "users") val users: List ) { fun getFlatRepresentation() = ArrayList().apply { @@ -66,17 +59,13 @@ data class ExactSharees( @JsonClass(generateAdapter = true) data class ShareeItem( - @Json(name = "label") val label: String, - @Json(name = "value") val value: ShareeValue ) @JsonClass(generateAdapter = true) data class ShareeValue( - @Json(name = "shareType") val shareType: Int, - @Json(name = "shareWith") val shareWith: String, @Json(name = "shareWithAdditionalInfo") val additionalInfo: String? diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt similarity index 75% rename from owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt rename to owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt index a1646b67..5c27f8ad 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt @@ -1,12 +1,35 @@ -package com.owncloud.android.lib +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2020 ownCloud 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.shares.responses import com.owncloud.android.lib.resources.CommonOcsResponse -import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types -import junit.framework.Assert.assertEquals -import junit.framework.Assert.assertTrue +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue import org.junit.Assert.assertNotEquals import org.junit.Before import org.junit.Test From 6ec1bd2bb278c2b39abbc5ef5797dbc6ff8ce05c Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 20 Oct 2020 14:08:39 +0200 Subject: [PATCH 30/41] move response json to resource folder --- .../shares/GetRemoteShareesOperation.kt | 3 - .../lib/resources/shares/RemoteShare.kt | 1 - .../implementation/OCShareeService.kt | 2 - .../shares/responses/ShareeResponseTest.kt | 112 ++++++------------ .../empty_sharee_response.json | 21 ++++ .../example_sharee_response.json | 60 ++++++++++ 6 files changed, 114 insertions(+), 85 deletions(-) create mode 100644 owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json create mode 100644 owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index 91271f0a..29875361 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -41,12 +41,9 @@ import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types -import org.json.JSONArray -import org.json.JSONObject import timber.log.Timber import java.lang.reflect.Type import java.net.URL -import java.util.ArrayList /** * Created by masensio on 08/10/2015. diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt index ac33ff81..f63f6503 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt @@ -24,7 +24,6 @@ package com.owncloud.android.lib.resources.shares -import com.owncloud.android.lib.resources.files.FileUtils import java.io.File /** diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt index 1ba7e0cb..9cb014f3 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt @@ -25,8 +25,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse import com.owncloud.android.lib.resources.shares.services.ShareeService -import org.json.JSONObject -import java.util.ArrayList class OCShareeService(override val client: OwnCloudClient) : ShareeService { diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt index 5c27f8ad..65afe4d9 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt @@ -29,140 +29,94 @@ import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import java.io.File import java.lang.reflect.Type class ShareeResponseTest { - var response: CommonOcsResponse? = null + lateinit var response: CommonOcsResponse + + private fun loadResponses(fileName: String, adapter: JsonAdapter>) = + adapter.fromJson(File(fileName).readText()) @Before fun prepare() { val moshi = Moshi.Builder().build() val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) val adapter: JsonAdapter> = moshi.adapter(type) - response = adapter.fromJson(EXAMPLE_RESPONSE) + response = loadResponses(EXAMPLE_RESPONSE_JSON, adapter)!! } @Test fun `check structure - ok - contains meta`() { - assertEquals("OK", response?.ocs?.meta?.message!!) - assertEquals(200, response?.ocs?.meta?.statusCode!!) - assertEquals("ok", response?.ocs?.meta?.status!!) - assertTrue(response?.ocs?.meta?.itemsPerPage?.isEmpty()!!) - assertTrue(response?.ocs?.meta?.totalItems?.isEmpty()!!) + assertEquals("OK", response.ocs.meta.message!!) + assertEquals(200, response.ocs.meta.statusCode!!) + assertEquals("ok", response.ocs.meta.status!!) + assertTrue(response.ocs.meta.itemsPerPage?.isEmpty()!!) + assertTrue(response.ocs.meta.totalItems?.isEmpty()!!) } @Test fun `check structure - ok - contains exact`() { - assertNotEquals(null, response?.ocs?.data?.exact) + assertNotEquals(null, response.ocs.data.exact) } @Test fun `check structure - ok - contains groups`() { - assertNotEquals(null, response?.ocs?.data?.groups) + assertNotEquals(null, response.ocs.data.groups) } @Test fun `check structure - ok - contains remotes`() { - assertNotEquals(null, response?.ocs?.data?.remotes) + assertNotEquals(null, response.ocs.data.remotes) } @Test fun `check structure - ok - contains users`() { - assertNotEquals(null, response?.ocs?.data?.users) + assertNotEquals(null, response.ocs.data.users) } @Test fun `check structure - ok - groups contains two items`() { - assertEquals(2, response?.ocs?.data?.groups?.size) + assertEquals(2, response.ocs.data.groups.size) } @Test fun `check structure - ok - users contains two items`() { - assertEquals(2, response?.ocs?.data?.users?.size) + assertEquals(2, response.ocs.data.users.size) } @Test fun `check structure - ok - exact_users contains one item`() { - assertEquals(1, response?.ocs?.data?.exact?.users?.size) + assertEquals(1, response.ocs.data.exact?.users?.size) } @Test fun `check structure - ok - user1 contains additional data`() { - assertEquals("user1@user1.com", response?.ocs?.data?.users?.get(0)?.value?.additionalInfo) + assertEquals("user1@user1.com", response.ocs.data.users.get(0).value.additionalInfo) } @Test fun `check structure - ok - user2 does not contain additional data`() { - assertEquals(null, response!!.ocs.data.users!![1].value!!.additionalInfo) + assertEquals(null, response.ocs.data.users[1].value.additionalInfo) + } + + @Test + fun `check empty response - ok - parsing ok`() { + val moshi = Moshi.Builder().build() + val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + loadResponses(EMPTY_RESPONSE_JSON, adapter)!! } companion object { - val EXAMPLE_RESPONSE = """ -{ - "ocs": { - "data": { - "exact": { - "groups": [], - "remotes": [], - "users": [ - { - "label": "admin", - "value": { - "shareType": 0, - "shareWith": "admin" - } - } - ] - }, - "groups": [ - { - "label": "group1", - "value": { - "shareType": 1, - "shareWith": "group1" - } - }, - { - "label": "group2", - "value": { - "shareType": 1, - "shareWith": "group2" - } - } - ], - "remotes": [], - "users": [ - { - "label": "user1", - "value": { - "shareType": 0, - "shareWith": "user1", - "shareWithAdditionalInfo": "user1@user1.com" - } - }, - { - "label": "user2", - "value": { - "shareType": 0, - "shareWith": "user2" - } - } - ] - }, - "meta": { - "itemsperpage": "", - "message": "OK", - "status": "ok", - "statuscode": 200, - "totalitems": "" - } - } -} - """ + val RESOURCES_PATH = + "/home/schabi/Projects/owncloud-android/owncloud-android-library/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses" + val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/example_sharee_response.json" + val EMPTY_RESPONSE_JSON = "$RESOURCES_PATH/empty_sharee_response.json" } } \ No newline at end of file diff --git a/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json b/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json new file mode 100644 index 00000000..b74338d2 --- /dev/null +++ b/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json @@ -0,0 +1,21 @@ +{ + "ocs": { + "meta": { + "status": "ok", + "statuscode": 100, + "message": "OK", + "totalitems": "", + "itemsperpage": "" + }, + "data": { + "exact": { + "users": [], + "groups": [], + "remotes": [] + }, + "users": [], + "groups": [], + "remotes": [] + } + } +} \ No newline at end of file diff --git a/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json b/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json new file mode 100644 index 00000000..fe988811 --- /dev/null +++ b/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json @@ -0,0 +1,60 @@ +{ + "ocs": { + "data": { + "exact": { + "groups": [], + "remotes": [], + "users": [ + { + "label": "admin", + "value": { + "shareType": 0, + "shareWith": "admin" + } + } + ] + }, + "groups": [ + { + "label": "group1", + "value": { + "shareType": 1, + "shareWith": "group1" + } + }, + { + "label": "group2", + "value": { + "shareType": 1, + "shareWith": "group2" + } + } + ], + "remotes": [], + "users": [ + { + "label": "user1", + "value": { + "shareType": 0, + "shareWith": "user1", + "shareWithAdditionalInfo": "user1@user1.com" + } + }, + { + "label": "user2", + "value": { + "shareType": 0, + "shareWith": "user2" + } + } + ] + }, + "meta": { + "itemsperpage": "", + "message": "OK", + "status": "ok", + "statuscode": 200, + "totalitems": "" + } + } +} \ No newline at end of file From 257494a9dcebb131c9b598db1cb4b0e716dc006c Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Wed, 21 Oct 2020 14:11:32 +0200 Subject: [PATCH 31/41] apply suggested changes delete unused const values bla --- .../lib/resources/shares/GetRemoteShareesOperation.kt | 7 ------- .../owncloud/android/lib/resources/shares/RemoteShare.kt | 3 +-- .../lib/resources/shares/responses/ShareeResponseTest.kt | 8 +++++++- .../empty_sharee_response.json | 0 .../example_sharee_response.json | 0 5 files changed, 8 insertions(+), 10 deletions(-) rename owncloudComLibrary/src/test/{resources => responses}/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json (100%) rename owncloudComLibrary/src/test/{resources => responses}/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json (100%) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt index 29875361..546bf05b 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.kt @@ -164,12 +164,5 @@ class GetRemoteShareesOperation // Arguments - constant values private const val VALUE_FORMAT = "json" private const val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups - - // JSON Node names - const val NODE_VALUE = "value" - const val PROPERTY_LABEL = "label" - const val PROPERTY_SHARE_TYPE = "shareType" - const val PROPERTY_SHARE_WITH = "shareWith" - const val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo" } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt index f63f6503..21e3835b 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt @@ -105,7 +105,6 @@ enum class ShareType constructor(val value: Int) { FEDERATED(6); companion object { - private val values = values(); - fun fromValue(value: Int) = values.firstOrNull { it.value == value } + fun fromValue(value: Int) = values().firstOrNull { it.value == value } } } diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt index 65afe4d9..5bd48cf0 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt @@ -51,6 +51,12 @@ class ShareeResponseTest { response = loadResponses(EXAMPLE_RESPONSE_JSON, adapter)!! } + @Test + fun `check structure - ok - example response files exist`() { + val file = File(EXAMPLE_RESPONSE_JSON) + assertTrue(file.exists()) + } + @Test fun `check structure - ok - contains meta`() { assertEquals("OK", response.ocs.meta.message!!) @@ -115,7 +121,7 @@ class ShareeResponseTest { companion object { val RESOURCES_PATH = - "/home/schabi/Projects/owncloud-android/owncloud-android-library/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses" + "src/test/responses/com.owncloud.android.lib.resources.sharees.responses" val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/example_sharee_response.json" val EMPTY_RESPONSE_JSON = "$RESOURCES_PATH/empty_sharee_response.json" } diff --git a/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json b/owncloudComLibrary/src/test/responses/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json similarity index 100% rename from owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json rename to owncloudComLibrary/src/test/responses/com.owncloud.android.lib.resources.sharees.responses/empty_sharee_response.json diff --git a/owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json b/owncloudComLibrary/src/test/responses/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json similarity index 100% rename from owncloudComLibrary/src/test/resources/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json rename to owncloudComLibrary/src/test/responses/com.owncloud.android.lib.resources.sharees.responses/example_sharee_response.json From ce9fc3f189f4f50e99a9224dd9ef914f5a49fc64 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 22 Oct 2020 12:40:48 +0200 Subject: [PATCH 32/41] apply changes acording to review --- .../shares/responses/ShareeResponseTest.kt | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt index 5bd48cf0..7640e5f5 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt @@ -28,8 +28,9 @@ import com.owncloud.android.lib.resources.CommonOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -38,85 +39,91 @@ import java.lang.reflect.Type class ShareeResponseTest { - lateinit var response: CommonOcsResponse + lateinit var adapter: JsonAdapter> - private fun loadResponses(fileName: String, adapter: JsonAdapter>) = + private fun loadResponses(fileName: String) = adapter.fromJson(File(fileName).readText()) @Before fun prepare() { val moshi = Moshi.Builder().build() val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) - val adapter: JsonAdapter> = moshi.adapter(type) - response = loadResponses(EXAMPLE_RESPONSE_JSON, adapter)!! - } - - @Test - fun `check structure - ok - example response files exist`() { - val file = File(EXAMPLE_RESPONSE_JSON) - assertTrue(file.exists()) + adapter = moshi.adapter(type) } @Test fun `check structure - ok - contains meta`() { + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals("OK", response.ocs.meta.message!!) - assertEquals(200, response.ocs.meta.statusCode!!) - assertEquals("ok", response.ocs.meta.status!!) + assertEquals(200, response.ocs.meta.statusCode) + assertEquals("ok", response.ocs.meta.status) assertTrue(response.ocs.meta.itemsPerPage?.isEmpty()!!) assertTrue(response.ocs.meta.totalItems?.isEmpty()!!) } @Test fun `check structure - ok - contains exact`() { - assertNotEquals(null, response.ocs.data.exact) + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertNotNull(response.ocs.data.exact) } @Test fun `check structure - ok - contains groups`() { - assertNotEquals(null, response.ocs.data.groups) + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertNotNull(response.ocs.data.groups) } @Test fun `check structure - ok - contains remotes`() { - assertNotEquals(null, response.ocs.data.remotes) + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertNotNull(response.ocs.data.remotes) } @Test fun `check structure - ok - contains users`() { - assertNotEquals(null, response.ocs.data.users) + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertNotNull(response.ocs.data.users) } @Test fun `check structure - ok - groups contains two items`() { + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals(2, response.ocs.data.groups.size) } @Test fun `check structure - ok - users contains two items`() { + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals(2, response.ocs.data.users.size) } @Test fun `check structure - ok - exact_users contains one item`() { + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals(1, response.ocs.data.exact?.users?.size) } @Test fun `check structure - ok - user1 contains additional data`() { + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals("user1@user1.com", response.ocs.data.users.get(0).value.additionalInfo) } @Test fun `check structure - ok - user2 does not contain additional data`() { - assertEquals(null, response.ocs.data.users[1].value.additionalInfo) + val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertNull(response.ocs.data.users[1].value.additionalInfo) } @Test fun `check empty response - ok - parsing ok`() { - val moshi = Moshi.Builder().build() - val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java) - val adapter: JsonAdapter> = moshi.adapter(type) - loadResponses(EMPTY_RESPONSE_JSON, adapter)!! + val response = loadResponses(EMPTY_RESPONSE_JSON)!! + assertTrue(response.ocs.data.exact?.groups?.isEmpty()!!) + assertTrue(response.ocs.data.exact?.remotes?.isEmpty()!!) + assertTrue(response.ocs.data.exact?.users?.isEmpty()!!) + assertTrue(response.ocs.data.groups.isEmpty()) + assertTrue(response.ocs.data.remotes.isEmpty()) + assertTrue(response.ocs.data.users.isEmpty()) } companion object { From 68b88775e6e844e150a8f4ec35c616a657c0a354 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Thu, 22 Oct 2020 13:05:50 +0200 Subject: [PATCH 33/41] apply changes acording to review --- .../shares/responses/ShareeResponseTest.kt | 50 ++----------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt index 7640e5f5..ee88839d 100644 --- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt +++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt @@ -28,7 +28,6 @@ import com.owncloud.android.lib.resources.CommonOcsResponse import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types -import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue @@ -62,56 +61,15 @@ class ShareeResponseTest { } @Test - fun `check structure - ok - contains exact`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! - assertNotNull(response.ocs.data.exact) - } - - @Test - fun `check structure - ok - contains groups`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! - assertNotNull(response.ocs.data.groups) - } - - @Test - fun `check structure - ok - contains remotes`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! - assertNotNull(response.ocs.data.remotes) - } - - @Test - fun `check structure - ok - contains users`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! - assertNotNull(response.ocs.data.users) - } - - @Test - fun `check structure - ok - groups contains two items`() { + fun `example response - ok - correct sturcture`() { val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals(2, response.ocs.data.groups.size) - } - - @Test - fun `check structure - ok - users contains two items`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertEquals(0, response.ocs.data.remotes.size) assertEquals(2, response.ocs.data.users.size) - } - - @Test - fun `check structure - ok - exact_users contains one item`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! + assertEquals(0, response.ocs.data.exact?.groups?.size) + assertEquals(0, response.ocs.data.exact?.remotes?.size) assertEquals(1, response.ocs.data.exact?.users?.size) - } - - @Test - fun `check structure - ok - user1 contains additional data`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertEquals("user1@user1.com", response.ocs.data.users.get(0).value.additionalInfo) - } - - @Test - fun `check structure - ok - user2 does not contain additional data`() { - val response = loadResponses(EXAMPLE_RESPONSE_JSON)!! assertNull(response.ocs.data.users[1].value.additionalInfo) } From 3441f4048c7210d95bde115d05e7a7627a67c8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 3 Nov 2020 11:46:20 +0100 Subject: [PATCH 34/41] Convert long shareId to String --- .../lib/resources/shares/GetRemoteShareOperation.java | 6 +++--- .../owncloud/android/lib/resources/shares/RemoteShare.kt | 5 ++--- .../lib/resources/shares/RemoveRemoteShareOperation.kt | 4 ++-- .../android/lib/resources/shares/ShareXMLParser.kt | 8 +++----- .../lib/resources/shares/UpdateRemoteShareOperation.kt | 2 +- .../android/lib/resources/shares/services/ShareService.kt | 4 ++-- .../shares/services/implementation/OCShareService.kt | 4 ++-- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java index 4b815df1..9e71252e 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java @@ -46,9 +46,9 @@ import java.net.URL; public class GetRemoteShareOperation extends RemoteOperation { - private long mRemoteId; + private String mRemoteId; - public GetRemoteShareOperation(long remoteId) { + public GetRemoteShareOperation(String remoteId) { mRemoteId = remoteId; } @@ -60,7 +60,7 @@ public class GetRemoteShareOperation extends RemoteOperation Uri requestUri = client.getBaseUri(); Uri.Builder uriBuilder = requestUri.buildUpon(); uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH); - uriBuilder.appendEncodedPath(Long.toString(mRemoteId)); + uriBuilder.appendEncodedPath(mRemoteId); GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString())); getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt index 21e3835b..83149d8e 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt @@ -34,7 +34,7 @@ import java.io.File * @author David González Verdugo */ data class RemoteShare( - var id: Long = 0, + var id: String = "0", var shareWith: String = "", var path: String = "", var token: String = "", @@ -49,8 +49,7 @@ data class RemoteShare( var sharedDate: Long = INIT_SHARED_DATE, var expirationDate: Long = INIT_EXPIRATION_DATE_IN_MILLIS, var isFolder: Boolean = path.endsWith(File.separator), - var userId: Long = 0, - val isValid: Boolean = id > -1 + var userId: Long = 0 ) { companion object { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.kt index 5fa18169..a7d18e5d 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.kt @@ -48,7 +48,7 @@ import java.net.URL * * @param remoteShareId Share ID */ -class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperation() { +class RemoveRemoteShareOperation(private val remoteShareId: String) : RemoteOperation() { override fun run(client: OwnCloudClient): RemoteOperationResult { var result: RemoteOperationResult @@ -57,7 +57,7 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat val requestUri = client.baseUri val uriBuilder = requestUri.buildUpon() uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH) - uriBuilder.appendEncodedPath(remoteShareId.toString()) + uriBuilder.appendEncodedPath(remoteShareId) val deleteMethod = DeleteMethod( URL(uriBuilder.build().toString()) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt index a63c35a7..75160d8d 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt @@ -179,7 +179,7 @@ class ShareXMLParser { name.equals(NODE_ID, ignoreCase = true) -> {// Parse Create XML Response share = RemoteShare() val value = readNode(parser, NODE_ID) - share.id = Integer.parseInt(value).toLong() + share.id = value } name.equals(NODE_URL, ignoreCase = true) -> { // NOTE: this field is received in all the public shares from OC 9.0.0 @@ -236,7 +236,7 @@ class ShareXMLParser { } name.equals(NODE_ID, ignoreCase = true) -> { - remoteShare.id = Integer.parseInt(readNode(parser, NODE_ID)).toLong() + remoteShare.id = readNode(parser, NODE_ID) } name.equals(NODE_ITEM_TYPE, ignoreCase = true) -> { @@ -320,9 +320,7 @@ class ShareXMLParser { } } - if (remoteShare.isValid) { - shares.add(remoteShare) - } + shares.add(remoteShare) } private fun fixPathForFolder(share: RemoteShare) { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/UpdateRemoteShareOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/UpdateRemoteShareOperation.kt index e2af8959..0df80bc9 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/UpdateRemoteShareOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/UpdateRemoteShareOperation.kt @@ -55,7 +55,7 @@ class UpdateRemoteShareOperation /** * @param remoteId Identifier of the share to update. */ - private val remoteId: Long + private val remoteId: String ) : RemoteOperation() { /** diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt index 38980256..caca3cd8 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt @@ -44,7 +44,7 @@ interface ShareService : Service { ): RemoteOperationResult fun updateShare( - remoteId: Long, + remoteId: String, name: String, password: String?, expirationDate: Long, @@ -52,5 +52,5 @@ interface ShareService : Service { publicUpload: Boolean ): RemoteOperationResult - fun deleteShare(remoteId: Long): RemoteOperationResult + fun deleteShare(remoteId: String): RemoteOperationResult } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareService.kt index a22919bf..109c2204 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareService.kt @@ -66,7 +66,7 @@ class OCShareService(override val client: OwnCloudClient) : }.execute(client) override fun updateShare( - remoteId: Long, + remoteId: String, name: String, password: String?, expirationDate: Long, @@ -84,7 +84,7 @@ class OCShareService(override val client: OwnCloudClient) : this.retrieveShareDetails = true }.execute(client) - override fun deleteShare(remoteId: Long): RemoteOperationResult = + override fun deleteShare(remoteId: String): RemoteOperationResult = RemoveRemoteShareOperation( remoteId ).execute(client) From 20c7c88a1fbdf6ecf24498f8ff0baf45e9c23ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 3 Nov 2020 18:31:51 +0100 Subject: [PATCH 35/41] Remove item_source and file_source --- .../android/lib/resources/shares/RemoteShare.kt | 5 +---- .../android/lib/resources/shares/ShareXMLParser.kt | 10 ---------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt index 83149d8e..320da5fc 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/RemoteShare.kt @@ -42,14 +42,11 @@ data class RemoteShare( var sharedWithAdditionalInfo: String = "", var name: String = "", var shareLink: String = "", - var fileSource: String = "0", - var itemSource: String = "0", var shareType: ShareType? = ShareType.UNKNOWN, var permissions: Int = DEFAULT_PERMISSION, var sharedDate: Long = INIT_SHARED_DATE, var expirationDate: Long = INIT_EXPIRATION_DATE_IN_MILLIS, - var isFolder: Boolean = path.endsWith(File.separator), - var userId: Long = 0 + var isFolder: Boolean = path.endsWith(File.separator) ) { companion object { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt index 75160d8d..389d6f3f 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareXMLParser.kt @@ -244,10 +244,6 @@ class ShareXMLParser { fixPathForFolder(remoteShare) } - name.equals(NODE_ITEM_SOURCE, ignoreCase = true) -> { - remoteShare.itemSource = readNode(parser, NODE_ITEM_SOURCE) - } - name.equals(NODE_PARENT, ignoreCase = true) -> { readNode(parser, NODE_PARENT) } @@ -261,10 +257,6 @@ class ShareXMLParser { remoteShare.shareWith = readNode(parser, NODE_SHARE_WITH) } - name.equals(NODE_FILE_SOURCE, ignoreCase = true) -> { - remoteShare.fileSource = readNode(parser, NODE_FILE_SOURCE) - } - name.equals(NODE_PATH, ignoreCase = true) -> { remoteShare.path = readNode(parser, NODE_PATH) fixPathForFolder(remoteShare) @@ -401,11 +393,9 @@ class ShareXMLParser { private const val NODE_ELEMENT = "element" private const val NODE_ID = "id" private const val NODE_ITEM_TYPE = "item_type" - private const val NODE_ITEM_SOURCE = "item_source" private const val NODE_PARENT = "parent" private const val NODE_SHARE_TYPE = "share_type" private const val NODE_SHARE_WITH = "share_with" - private const val NODE_FILE_SOURCE = "file_source" private const val NODE_PATH = "path" private const val NODE_PERMISSIONS = "permissions" private const val NODE_STIME = "stime" From 0eeb48f7de9c37684d390e9e562abe1606a7ddeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 24 Nov 2020 08:52:09 +0100 Subject: [PATCH 36/41] Move appauth dependency to ownCloudApp --- owncloudComLibrary/build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 5537f94e..3aa8f167 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -7,7 +7,6 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" api 'com.gitlab.ownclouders:dav4android:oc_support_2.1.5' api 'com.github.AppDevNext.Logcat:LogcatCore:2.1.1' - api 'net.openid:appauth:0.7.1' // Moshi implementation ("com.squareup.moshi:moshi-kotlin:$moshiVersion") { @@ -27,10 +26,6 @@ android { versionCode = 10000800 versionName = "1.0.8" - - // This is pretty ugly but manifest placeholders don't seem to work very well when using different modules - // See https://github.com/openid/AppAuth-Android/issues/325 - manifestPlaceholders = [appAuthRedirectScheme: ''] } lintOptions { From 102747c392dcc834f622371a13440b46fccafe02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 2 Dec 2020 13:46:45 +0100 Subject: [PATCH 37/41] Android Studio 4.1.1 --- build.gradle | 4 ++-- owncloudComLibrary/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 07767bc9..5cb2900a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlinVersion = '1.4.10' + kotlinVersion = '1.4.20' moshiVersion = "1.9.2" } @@ -9,7 +9,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" } } diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 3aa8f167..b59cc1fd 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -14,7 +14,7 @@ dependencies { } kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" - testImplementation 'junit:junit:4.13' + testImplementation 'junit:junit:4.13.1' } android { From 2a4f8175daa7092c9189bc5b917453e726660250 Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Mon, 14 Dec 2020 08:19:59 +0100 Subject: [PATCH 38/41] Show logcat live It updates logcat content during observation --- owncloudComLibrary/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index b59cc1fd..98d7dc99 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -6,7 +6,7 @@ dependencies { api 'com.squareup.okhttp3:okhttp:4.6.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" api 'com.gitlab.ownclouders:dav4android:oc_support_2.1.5' - api 'com.github.AppDevNext.Logcat:LogcatCore:2.1.1' + api 'com.github.AppDevNext.Logcat:LogcatCore:2.2.1' // Moshi implementation ("com.squareup.moshi:moshi-kotlin:$moshiVersion") { From cd8878352db17d7c3835aa899a264ff57fe96f05 Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Wed, 16 Dec 2020 14:09:22 +0100 Subject: [PATCH 39/41] delete logcat history --- owncloudComLibrary/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 98d7dc99..90a29ef8 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -6,7 +6,7 @@ dependencies { api 'com.squareup.okhttp3:okhttp:4.6.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" api 'com.gitlab.ownclouders:dav4android:oc_support_2.1.5' - api 'com.github.AppDevNext.Logcat:LogcatCore:2.2.1' + api 'com.github.AppDevNext.Logcat:LogcatCore:2.2.2' // Moshi implementation ("com.squareup.moshi:moshi-kotlin:$moshiVersion") { From 114a7221f361d21dc815371de2839840f394289d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 22 Dec 2020 10:50:20 +0100 Subject: [PATCH 40/41] Use constants instead of hardcoded values for dir mimetypes --- .../lib/resources/files/FileUtils.java | 2 ++ .../lib/resources/files/RemoteFile.java | 25 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/FileUtils.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/FileUtils.java index 481ca168..cc159611 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/FileUtils.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/FileUtils.java @@ -30,6 +30,8 @@ import java.io.File; public class FileUtils { public static final String FINAL_CHUNKS_FILE = ".file"; + public static final String MIME_DIR = "DIR"; + public static final String MIME_DIR_UNIX = "httpd/unix-directory"; static String getParentPath(String remotePath) { String parentPath = new File(remotePath).getParent(); diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RemoteFile.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RemoteFile.java index cb390993..0557f99e 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RemoteFile.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RemoteFile.java @@ -29,7 +29,17 @@ import android.os.Parcelable; import at.bitfire.dav4jvm.Property; import at.bitfire.dav4jvm.Response; -import at.bitfire.dav4jvm.property.*; +import at.bitfire.dav4jvm.property.CreationDate; +import at.bitfire.dav4jvm.property.GetContentLength; +import at.bitfire.dav4jvm.property.GetContentType; +import at.bitfire.dav4jvm.property.GetETag; +import at.bitfire.dav4jvm.property.GetLastModified; +import at.bitfire.dav4jvm.property.OCId; +import at.bitfire.dav4jvm.property.OCPermissions; +import at.bitfire.dav4jvm.property.OCPrivatelink; +import at.bitfire.dav4jvm.property.OCSize; +import at.bitfire.dav4jvm.property.QuotaAvailableBytes; +import at.bitfire.dav4jvm.property.QuotaUsedBytes; import java.io.File; import java.io.Serializable; @@ -83,7 +93,8 @@ public class RemoteFile implements Parcelable, Serializable { /** * Create new {@link RemoteFile} with given path. *

- * The path received must be URL-decoded. Path separator must be File.separator, and it must be the first character in 'path'. + * The path received must be URL-decoded. Path separator must be File.separator, and it must be the first + * character in 'path'. * * @param path The remote path of the file. */ @@ -95,7 +106,7 @@ public class RemoteFile implements Parcelable, Serializable { mRemotePath = path; mCreationTimestamp = 0; mLength = 0; - mMimeType = "DIR"; + mMimeType = FileUtils.MIME_DIR; mQuotaUsedBytes = BigDecimal.ZERO; mQuotaAvailableBytes = BigDecimal.ZERO; mPrivateLink = null; @@ -154,6 +165,14 @@ public class RemoteFile implements Parcelable, Serializable { readFromParcel(source); } + /** + * Use this to find out if this file is a folder. + * + * @return true if it is a folder + */ + public boolean isFolder() { + return mMimeType != null && (mMimeType.equals(FileUtils.MIME_DIR) || mMimeType.equals(FileUtils.MIME_DIR_UNIX)); + } /** * Getters and Setters From 65a4aaac28cbc275ea74d7f3f09693b4a899ef30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Mon, 18 Jan 2021 09:21:47 +0100 Subject: [PATCH 41/41] Release 1.0.9 Update versionName and versionCode --- owncloudComLibrary/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 90a29ef8..0a003a08 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -24,8 +24,8 @@ android { minSdkVersion 21 targetSdkVersion 29 - versionCode = 10000800 - versionName = "1.0.8" + versionCode = 10000900 + versionName = "1.0.9" } lintOptions {