diff --git a/build.gradle b/build.gradle index c0052708..c22d1831 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ buildscript { ext { kotlinVersion = '1.3.71' + moshiVersion = "1.9.2" } repositories { diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle index 82949174..d18e80ea 100644 --- a/owncloudComLibrary/build.gradle +++ b/owncloudComLibrary/build.gradle @@ -9,6 +9,12 @@ dependencies { api 'com.gitlab.ownclouders:dav4android:oc_support_1.0.1' api 'com.github.hannesa2:Logcat:1.6.0' api 'net.openid:appauth:0.7.1' + + // Moshi + implementation ("com.squareup.moshi:moshi-kotlin:$moshiVersion") { + exclude module: "kotlin-reflect" + } + kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" } allOpen { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java index 5c4ae8e6..3ab812d4 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java @@ -53,6 +53,7 @@ import static com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID public class OwnCloudClient extends HttpClient { public static final String WEBDAV_FILES_PATH_4_0 = "/remote.php/dav/files/"; + public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/dav"; private static final String WEBDAV_UPLOADS_PATH_4_0 = "/remote.php/dav/uploads/"; public static final String STATUS_PATH = "/status.php"; @@ -230,7 +231,7 @@ public class OwnCloudClient extends HttpClient { } public Uri getUserFilesWebDavUri() { - return mCredentials instanceof OwnCloudAnonymousCredentials + return (mCredentials instanceof OwnCloudAnonymousCredentials || mAccount == null) ? Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0) : Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId( mAccount.getSavedAccount(), getContext() diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/accounts/AccountUtils.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/accounts/AccountUtils.java index b2ab1880..8451edb1 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/accounts/AccountUtils.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/accounts/AccountUtils.java @@ -46,7 +46,6 @@ import java.util.ArrayList; import java.util.List; public class AccountUtils { - /** * Constructs full url to host and webdav resource basing on host version * @@ -140,7 +139,7 @@ public class AccountUtils { AccountManager am = AccountManager.get(context); String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2); - boolean isOauth2 = supportsOAuth2 != null && supportsOAuth2.equals("TRUE"); + boolean isOauth2 = supportsOAuth2 != null && supportsOAuth2.equals(Constants.OAUTH_SUPPORTED_TRUE); String username = AccountUtils.getUsernameForAccount(account); @@ -295,6 +294,8 @@ public class AccountUtils { */ public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2"; + public static final String OAUTH_SUPPORTED_TRUE = "TRUE"; + /** * OC account cookies */ @@ -329,5 +330,7 @@ public class AccountUtils { * OAuth2 scope */ public static final String KEY_OAUTH2_SCOPE = "oc_oauth2_scope"; + + public static final int ACCOUNT_VERSION = 1; } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java index 45b7f35f..5647dec4 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java @@ -34,11 +34,12 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -public class WebdavUtils { - public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat( - "dd.MM.yyyy hh:mm"); +import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0; +import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_PATH_4_0_AND_LATER; - private static final SimpleDateFormat DATETIME_FORMATS[] = { +public class WebdavUtils { + + private static final SimpleDateFormat[] DATETIME_FORMATS = { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US), @@ -50,11 +51,11 @@ public class WebdavUtils { }; public static Date parseResponseDate(String date) { - Date returnDate = null; - SimpleDateFormat format = null; - for (int i = 0; i < DATETIME_FORMATS.length; ++i) { + Date returnDate; + SimpleDateFormat format; + for (SimpleDateFormat datetimeFormat : DATETIME_FORMATS) { try { - format = DATETIME_FORMATS[i]; + format = datetimeFormat; synchronized (format) { returnDate = format.parse(date); } @@ -82,23 +83,6 @@ public class WebdavUtils { return encodedPath; } - /** - * @param rawEtag - * @return - */ - public static String parseEtag(String rawEtag) { - if (rawEtag == null || rawEtag.length() == 0) { - return ""; - } - if (rawEtag.endsWith("-gzip")) { - rawEtag = rawEtag.substring(0, rawEtag.length() - 5); - } - if (rawEtag.length() >= 2 && rawEtag.startsWith("\"") && rawEtag.endsWith("\"")) { - rawEtag = rawEtag.substring(1, rawEtag.length() - 1); - } - return rawEtag; - } - /** * @param httpBaseMethod from which to get the etag * @return etag from response @@ -120,4 +104,17 @@ public class WebdavUtils { } return result; } + + public static String normalizeProtocolPrefix(String url, boolean isSslConn) { + if (!url.toLowerCase().startsWith("http://") && + !url.toLowerCase().startsWith("https://")) { + if (isSslConn) { + return "https://" + url; + } else { + return "http://" + url; + } + } + return url; + } + } \ No newline at end of file diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index 0673fc0a..881aa0d2 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -66,7 +66,7 @@ public class RemoteOperationResult private Exception mException = null; private ResultCode mCode = ResultCode.UNKNOWN_ERROR; private String mRedirectedLocation; - private ArrayList mAuthenticate = new ArrayList<>(); + private String mAuthenticate; private String mLastPermanentLocation = null; private T mData = null; @@ -253,7 +253,7 @@ public class RemoteOperationResult continue; } if ("www-authenticate".equals(header.getKey().toLowerCase())) { - mAuthenticate.add(header.getValue().get(0).toLowerCase()); + mAuthenticate = header.getValue().get(0).toLowerCase(); } } } @@ -494,7 +494,7 @@ public class RemoteOperationResult return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://"))); } - public ArrayList getAuthenticateHeaders() { + public String getAuthenticateHeaders() { return mAuthenticate; } 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 new file mode 100644 index 00000000..2cfbe2ed --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/CommonOcsResponse.kt @@ -0,0 +1,46 @@ +/* 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 + +import com.squareup.moshi.JsonClass + +// Response retrieved by OCS Rest API, used to obtain capabilities, shares and user info among others. +// More info: https://doc.owncloud.com/server/developer_manual/core/apis/ocs-capabilities.html +@JsonClass(generateAdapter = true) +data class CommonOcsResponse( + val ocs: OCSResponse +) + +@JsonClass(generateAdapter = true) +data class OCSResponse( + val meta: MetaData, + val data: T +) + +@JsonClass(generateAdapter = true) +data class MetaData( + val status: String, + val statuscode: Int, + val message: String? +) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/CheckPathExistenceRemoteOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/CheckPathExistenceRemoteOperation.kt new file mode 100644 index 00000000..aafa5fc7 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/CheckPathExistenceRemoteOperation.kt @@ -0,0 +1,115 @@ +/* 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.files + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.http.HttpConstants +import com.owncloud.android.lib.common.http.methods.webdav.DavUtils +import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod +import com.owncloud.android.lib.common.network.RedirectionPath +import com.owncloud.android.lib.common.network.WebdavUtils +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 timber.log.Timber +import java.net.URL +import java.util.concurrent.TimeUnit + +/** + * Operation to check the existence of a path in a remote server. + * + * @author David A. Velasco + * @author David González Verdugo + * @author Abel García de Prada + * + * @param remotePath Path to append to the URL owned by the client instance. + * @param isUserLogged When `true`, the username won't be added at the end of the PROPFIND url since is not + * needed to check user credentials + */ +class CheckPathExistenceRemoteOperation( + val remotePath: String? = "", + val isUserLogged: Boolean +) : RemoteOperation() { + /** + * Gets the sequence of redirections followed during the execution of the operation. + * + * @return Sequence of redirections followed, if any, or NULL if the operation was not executed. + */ + var redirectionPath: RedirectionPath? = null + private set + + override fun run(client: OwnCloudClient): RemoteOperationResult { + val previousFollowRedirects = client.followRedirects() + return try { + val stringUrl = + if (isUserLogged) client.baseFilesWebDavUri.toString() + else client.userFilesWebDavUri.toString() + WebdavUtils.encodePath(remotePath) + + val propFindMethod = PropfindMethod(URL(stringUrl), 0, DavUtils.getAllPropset()).apply { + setReadTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS) + setConnectionTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS) + } + + client.setFollowRedirects(false) + var status = client.executeHttpMethod(propFindMethod) + if (previousFollowRedirects) { + redirectionPath = client.followRedirection(propFindMethod) + status = redirectionPath?.lastStatus!! + } + /* PROPFIND method + * 404 NOT FOUND: path doesn't exist, + * 207 MULTI_STATUS: path exists. + */ + Timber.d( + "Existence check for $stringUrl finished with HTTP status $status${if (!isSuccess(status)) "(FAIL)" else ""}" + ) + if (isSuccess(status)) RemoteOperationResult(ResultCode.OK).apply { data = true } + else RemoteOperationResult(propFindMethod).apply { data = false } + + } catch (e: Exception) { + val result = RemoteOperationResult(e) + Timber.e( + e, + "Existence check for ${client.userFilesWebDavUri}${WebdavUtils.encodePath(remotePath)} : ${result.logMessage}" + ) + result + } finally { + client.setFollowRedirects(previousFollowRedirects) + } + } + + /** + * @return 'True' if the operation was executed and at least one redirection was followed. + */ + fun wasRedirected() = redirectionPath?.redirectionsCount ?: 0 > 0 + + private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_MULTI_STATUS + + companion object { + /** + * Maximum time to wait for a response from the server in milliseconds. + */ + private const val TIMEOUT = 10000 + } +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java deleted file mode 100644 index 1a21fbf1..00000000 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java +++ /dev/null @@ -1,150 +0,0 @@ -/* 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.files; - -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.http.HttpConstants; -import com.owncloud.android.lib.common.http.methods.webdav.DavUtils; -import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod; -import com.owncloud.android.lib.common.network.RedirectionPath; -import com.owncloud.android.lib.common.network.WebdavUtils; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import timber.log.Timber; - -import java.net.URL; -import java.util.concurrent.TimeUnit; - -import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; - -/** - * Operation to check the existence or absence of a path in a remote server. - * - * @author David A. Velasco - * @author David González Verdugo - */ -public class ExistenceCheckRemoteOperation extends RemoteOperation { - - /** - * Maximum time to wait for a response from the server in MILLISECONDs. - */ - public static final int TIMEOUT = 10000; - - private String mPath; - private boolean mSuccessIfAbsent; - private boolean mIsLogin; - - /** - * Sequence of redirections followed. Available only after executing the operation - */ - private RedirectionPath mRedirectionPath = null; - - /** - * Full constructor. Success of the operation will depend upon the value of successIfAbsent. - * - * @param remotePath Path to append to the URL owned by the client instance. - * @param successIfAbsent When 'true', the operation finishes in success if the path does - * NOT exist in the remote server (HTTP 404). - * @param isLogin When `true`, the username won't be added at the end of the PROPFIND url since is not - * needed to check user credentials - */ - public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent, boolean isLogin) { - mPath = (remotePath != null) ? remotePath : ""; - mSuccessIfAbsent = successIfAbsent; - mIsLogin = isLogin; - } - - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - - boolean previousFollowRedirects = client.followRedirects(); - - try { - String stringUrl = mIsLogin ? - client.getBaseFilesWebDavUri().toString() : - client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mPath); - PropfindMethod propfindMethod = new PropfindMethod( - new URL(stringUrl), - 0, - DavUtils.getAllPropset() - ); - propfindMethod.setReadTimeout(TIMEOUT, TimeUnit.SECONDS); - propfindMethod.setConnectionTimeout(TIMEOUT, TimeUnit.SECONDS); - - client.setFollowRedirects(false); - int status = client.executeHttpMethod(propfindMethod); - - if (previousFollowRedirects) { - mRedirectionPath = client.followRedirection(propfindMethod); - status = mRedirectionPath.getLastStatus(); - } - - /* - * PROPFIND method - * 404 NOT FOUND: path doesn't exist, - * 207 MULTI_STATUS: path exists. - */ - - Timber.d("Existence check for " + stringUrl + WebdavUtils.encodePath(mPath) + - " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + - "finished with HTTP status " + status + (!isSuccess(status) ? "(FAIL)" : "")); - - return isSuccess(status) - ? new RemoteOperationResult<>(OK) - : new RemoteOperationResult<>(propfindMethod); - - } catch (Exception e) { - final RemoteOperationResult result = new RemoteOperationResult<>(e); - Timber.e(result.getException(), - "Existence check for " + client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mPath) + " " + - "targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage()); - return result; - } finally { - client.setFollowRedirects(previousFollowRedirects); - } - } - - /** - * Gets the sequence of redirections followed during the execution of the operation. - * - * @return Sequence of redirections followed, if any, or NULL if the operation was not executed. - */ - public RedirectionPath getRedirectionPath() { - return mRedirectionPath; - } - - /** - * @return 'True' if the operation was executed and at least one redirection was followed. - */ - public boolean wasRedirected() { - return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0); - } - - private boolean isSuccess(int status) { - return ((status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_MULTI_STATUS) && !mSuccessIfAbsent) - || (status == HttpConstants.HTTP_MULTI_STATUS && !mSuccessIfAbsent) - || (status == HttpConstants.HTTP_NOT_FOUND && mSuccessIfAbsent); - } -} \ No newline at end of file diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java index 221a133c..90a9c469 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java @@ -123,9 +123,9 @@ public class RenameRemoteFileOperation extends RemoteOperation { * @return 'True' if the target path is already used by an existing file. */ private boolean targetPathIsUsed(OwnCloudClient client) { - ExistenceCheckRemoteOperation existenceCheckRemoteOperation = - new ExistenceCheckRemoteOperation(mNewRemotePath, false, false); - RemoteOperationResult exists = existenceCheckRemoteOperation.run(client); + CheckPathExistenceRemoteOperation checkPathExistenceRemoteOperation = + new CheckPathExistenceRemoteOperation(mNewRemotePath, false); + RemoteOperationResult exists = checkPathExistenceRemoteOperation.execute(client); return exists.isSuccess(); } } \ No newline at end of file diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/FileService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/FileService.kt new file mode 100644 index 00000000..aa69d505 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/FileService.kt @@ -0,0 +1,31 @@ +/* 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.files.services + +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.Service + +interface FileService: Service { + fun checkPathExistence(path: String, isUserLogged: Boolean): RemoteOperationResult +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/implementation/OCFileService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/implementation/OCFileService.kt new file mode 100644 index 00000000..abe1e2e6 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/files/services/implementation/OCFileService.kt @@ -0,0 +1,34 @@ +/** + * ownCloud Android client application + * + * @author Abel García de Prada + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.lib.resources.files.services.implementation + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.files.CheckPathExistenceRemoteOperation +import com.owncloud.android.lib.resources.files.services.FileService + +class OCFileService(override val client: OwnCloudClient) : + FileService { + override fun checkPathExistence(path: String, isUserLogged: Boolean): RemoteOperationResult = + CheckPathExistenceRemoteOperation( + remotePath = path, + isUserLogged = isUserLogged + ).execute(client) +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt similarity index 89% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareService.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt index c0047fa8..38980256 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareService.kt @@ -18,10 +18,12 @@ * along with this program. If not, see . */ -package com.owncloud.android.lib.resources.shares +package com.owncloud.android.lib.resources.shares.services import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.Service +import com.owncloud.android.lib.resources.shares.ShareParserResult +import com.owncloud.android.lib.resources.shares.ShareType interface ShareService : Service { fun getShares( diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareeService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt similarity index 94% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareeService.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt index 8e7c8964..ab6d9e83 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/ShareeService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/ShareeService.kt @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -package com.owncloud.android.lib.resources.shares +package com.owncloud.android.lib.resources.shares.services import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.Service 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 new file mode 100644 index 00000000..a22919bf --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareService.kt @@ -0,0 +1,91 @@ +/** + * ownCloud Android client application + * + * @author David González Verdugo + * + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.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.CreateRemoteShareOperation +import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation +import com.owncloud.android.lib.resources.shares.RemoveRemoteShareOperation +import com.owncloud.android.lib.resources.shares.ShareParserResult +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.lib.resources.shares.UpdateRemoteShareOperation +import com.owncloud.android.lib.resources.shares.services.ShareService + +class OCShareService(override val client: OwnCloudClient) : + ShareService { + override fun getShares( + remoteFilePath: String, + reshares: Boolean, + subfiles: Boolean + ): RemoteOperationResult = GetRemoteSharesForFileOperation( + remoteFilePath, + reshares, + subfiles + ).execute(client) + + override fun insertShare( + remoteFilePath: String, + shareType: ShareType, + shareWith: String, + permissions: Int, + name: String, + password: String, + expirationDate: Long, + publicUpload: Boolean + ): RemoteOperationResult = + CreateRemoteShareOperation( + remoteFilePath, + shareType, + shareWith, + permissions + ).apply { + this.name = name + this.password = password + this.expirationDateInMillis = expirationDate + this.publicUpload = publicUpload + this.retrieveShareDetails = true + }.execute(client) + + override fun updateShare( + remoteId: Long, + name: String, + password: String?, + expirationDate: Long, + permissions: Int, + publicUpload: Boolean + ): RemoteOperationResult = + UpdateRemoteShareOperation( + remoteId + ).apply { + this.name = name + this.password = password + this.expirationDateInMillis = expirationDate + this.permissions = permissions + this.publicUpload = publicUpload + this.retrieveShareDetails = true + }.execute(client) + + override fun deleteShare(remoteId: Long): RemoteOperationResult = + RemoveRemoteShareOperation( + remoteId + ).execute(client) +} 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 new file mode 100644 index 00000000..370ef34b --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/shares/services/implementation/OCShareeService.kt @@ -0,0 +1,42 @@ +/** + * ownCloud Android client application + * + * @author David González Verdugo + * + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.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.services.ShareeService +import org.json.JSONObject +import java.util.ArrayList + +class OCShareeService(override val client: OwnCloudClient) : + ShareeService { + override fun getSharees( + searchString: String, + page: Int, + perPage: Int + ): RemoteOperationResult> = + GetRemoteShareesOperation( + searchString, + page, + perPage + ).execute(client) +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java deleted file mode 100644 index bab59562..00000000 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ /dev/null @@ -1,196 +0,0 @@ -/* 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.status; - -import android.content.Context; -import android.net.ConnectivityManager; -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 org.json.JSONException; -import org.json.JSONObject; -import timber.log.Timber; - -import javax.net.ssl.SSLException; -import java.net.URL; -import java.util.concurrent.TimeUnit; - -import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; - -/** - * Checks if the server is valid and if the server supports the Share API - * - * @author David A. Velasco - * @author masensio - * @author David González Verdugo - */ - -public class GetRemoteStatusOperation extends RemoteOperation { - - /** - * Maximum time to wait for a response from the server when the connection is being tested, - * in MILLISECONDs. - */ - public static final long TRY_CONNECTION_TIMEOUT = 5000; - - private static final String NODE_INSTALLED = "installed"; - private static final String NODE_VERSION = "version"; - private static final String HTTPS_PREFIX = "https://"; - private static final String HTTP_PREFIX = "http://"; - - private RemoteOperationResult mLatestResult; - private Context mContext; - - public GetRemoteStatusOperation(Context context) { - mContext = context; - } - - private boolean tryConnection(OwnCloudClient client) { - boolean retval = false; - String baseUrlSt = client.getBaseUri().toString(); - try { - GetMethod getMethod = new GetMethod(new URL(baseUrlSt + OwnCloudClient.STATUS_PATH)); - - getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS); - getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS); - - client.setFollowRedirects(false); - boolean isRedirectToNonSecureConnection = false; - int status; - try { - status = client.executeHttpMethod(getMethod); - mLatestResult = isSuccess(status) - ? new RemoteOperationResult<>(OK) - : new RemoteOperationResult<>(getMethod); - } catch (SSLException sslE) { - mLatestResult = new RemoteOperationResult(sslE); - return false; - } - - String redirectedLocation = mLatestResult.getRedirectedLocation(); - while (redirectedLocation != null && redirectedLocation.length() > 0 - && !mLatestResult.isSuccess()) { - - isRedirectToNonSecureConnection |= ( - baseUrlSt.startsWith(HTTPS_PREFIX) && - redirectedLocation.startsWith(HTTP_PREFIX) - ); - - getMethod = new GetMethod(new URL(redirectedLocation)); - getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS); - getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS); - - status = client.executeHttpMethod(getMethod); - mLatestResult = new RemoteOperationResult<>(getMethod); - redirectedLocation = mLatestResult.getRedirectedLocation(); - } - - if (isSuccess(status)) { - - JSONObject respJSON = new JSONObject(getMethod.getResponseBodyAsString()); - if (!respJSON.getBoolean(NODE_INSTALLED)) { - mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED); - } else { - String version = respJSON.getString(NODE_VERSION); - OwnCloudVersion ocVersion = new OwnCloudVersion(version); - /// the version object will be returned even if the version is invalid, no error code; - /// every app will decide how to act if (ocVersion.isVersionValid() == false) - - if (isRedirectToNonSecureConnection) { - mLatestResult = new RemoteOperationResult<>( - RemoteOperationResult.ResultCode. - OK_REDIRECT_TO_NON_SECURE_CONNECTION); - } else { - mLatestResult = new RemoteOperationResult<>( - baseUrlSt.startsWith(HTTPS_PREFIX) ? - RemoteOperationResult.ResultCode.OK_SSL : - RemoteOperationResult.ResultCode.OK_NO_SSL); - } - - mLatestResult.setData(ocVersion); - retval = true; - } - - } else { - mLatestResult = new RemoteOperationResult<>(getMethod); - } - - } catch (JSONException e) { - mLatestResult = new RemoteOperationResult<>( - RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED); - - } catch (Exception e) { - mLatestResult = new RemoteOperationResult<>(e); - } - - if (mLatestResult.isSuccess()) { - Timber.i("Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); - - } else if (mLatestResult.getException() != null) { - Timber.e(mLatestResult.getException(), "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); - - } else { - Timber.e("Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); - } - - return retval; - } - - private boolean isOnline() { - ConnectivityManager cm = (ConnectivityManager) mContext - .getSystemService(Context.CONNECTIVITY_SERVICE); - return cm != null && cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnectedOrConnecting(); - } - - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - if (!isOnline()) { - return new RemoteOperationResult<>(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION); - } - String baseUriStr = client.getBaseUri().toString(); - if (baseUriStr.startsWith(HTTP_PREFIX) || baseUriStr.startsWith(HTTPS_PREFIX)) { - tryConnection(client); - - } else { - client.setBaseUri(Uri.parse(HTTPS_PREFIX + baseUriStr)); - boolean httpsSuccess = tryConnection(client); - if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) { - Timber.d("Establishing secure connection failed, trying non secure connection"); - client.setBaseUri(Uri.parse(HTTP_PREFIX + baseUriStr)); - tryConnection(client); - } - } - return mLatestResult; - } - - private boolean isSuccess(int status) { - return (status == HttpConstants.HTTP_OK); - } -} \ No newline at end of file diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt new file mode 100644 index 00000000..b6fd1b39 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt @@ -0,0 +1,160 @@ +/* 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.status + +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 +import org.json.JSONException +import org.json.JSONObject +import timber.log.Timber +import java.net.URL +import java.util.concurrent.TimeUnit +import javax.net.ssl.SSLException + +/** + * Checks if the server is valid + * + * @author David A. Velasco + * @author masensio + * @author David González Verdugo + * @author Abel García de Prada + */ +class GetRemoteStatusOperation : RemoteOperation() { + private lateinit var latestResult: RemoteOperationResult + + override fun run(client: OwnCloudClient): RemoteOperationResult { + + val baseUriStr = client.baseUri.toString() + if (baseUriStr.startsWith(HTTP_PREFIX) || baseUriStr.startsWith( + HTTPS_PREFIX + )) { + tryConnection(client) + } else { + client.baseUri = Uri.parse(HTTPS_PREFIX + baseUriStr) + val httpsSuccess = tryConnection(client) + if (!httpsSuccess && !latestResult.isSslRecoverableException) { + Timber.d("Establishing secure connection failed, trying non secure connection") + client.baseUri = Uri.parse(HTTP_PREFIX + baseUriStr) + tryConnection(client) + } + } + return latestResult + } + + private fun tryConnection(client: OwnCloudClient): Boolean { + var successfulConnection = false + val baseUrlSt = client.baseUri.toString() + try { + var getMethod = GetMethod(URL(baseUrlSt + OwnCloudClient.STATUS_PATH)).apply { + setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS) + setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS) + } + client.setFollowRedirects(false) + var isRedirectToNonSecureConnection = false + var status: Int + try { + status = client.executeHttpMethod(getMethod) + latestResult = + if (isSuccess(status)) RemoteOperationResult(ResultCode.OK) + else RemoteOperationResult(getMethod) + + } catch (sslE: SSLException) { + latestResult = RemoteOperationResult(sslE) + return successfulConnection + } + + var redirectedLocation = latestResult.redirectedLocation + while (!redirectedLocation.isNullOrEmpty() && !latestResult.isSuccess) { + isRedirectToNonSecureConnection = + isRedirectToNonSecureConnection || + (baseUrlSt.startsWith(HTTPS_PREFIX) && redirectedLocation.startsWith( + HTTP_PREFIX + )) + + getMethod = GetMethod(URL(redirectedLocation)).apply { + setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS) + setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS) + } + + status = client.executeHttpMethod(getMethod) + latestResult = RemoteOperationResult(getMethod) + redirectedLocation = latestResult.redirectedLocation + } + + if (isSuccess(status)) { + val respJSON = JSONObject(getMethod.responseBodyAsString) + if (!respJSON.getBoolean(NODE_INSTALLED)) { + latestResult = RemoteOperationResult(ResultCode.INSTANCE_NOT_CONFIGURED) + } else { + val version = respJSON.getString(NODE_VERSION) + val ocVersion = OwnCloudVersion(version) + // the version object will be returned even if the version is invalid, no error code; + // every app will decide how to act if (ocVersion.isVersionValid() == false) + latestResult = if (isRedirectToNonSecureConnection) { + RemoteOperationResult(ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION) + } else { + if (baseUrlSt.startsWith(HTTPS_PREFIX)) RemoteOperationResult(ResultCode.OK_SSL) + else RemoteOperationResult(ResultCode.OK_NO_SSL) + } + latestResult.data = ocVersion + successfulConnection = true + } + } else { + latestResult = RemoteOperationResult(getMethod) + } + } catch (e: JSONException) { + latestResult = RemoteOperationResult(ResultCode.INSTANCE_NOT_CONFIGURED) + } catch (e: Exception) { + latestResult = RemoteOperationResult(e) + } + when { + latestResult.isSuccess -> Timber.i("Connection check at $baseUrlSt successful: ${latestResult.logMessage}") + + latestResult.isException -> + Timber.e(latestResult.exception, "Connection check at $baseUrlSt: ${latestResult.logMessage}") + + else -> Timber.e("Connection check at $baseUrlSt failed: ${latestResult.logMessage}") + } + return successfulConnection + } + + private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK + + companion object { + /** + * Maximum time to wait for a response from the server when the connection is being tested, + * in MILLISECONDs. + */ + private const val TRY_CONNECTION_TIMEOUT: Long = 5000 + private const val NODE_INSTALLED = "installed" + private const val NODE_VERSION = "version" + private const val HTTPS_PREFIX = "https://" + private const val HTTP_PREFIX = "http://" + } +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/CapabilityService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/CapabilityService.kt similarity index 88% rename from owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/CapabilityService.kt rename to owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/CapabilityService.kt index fab4f301..0ad809c8 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/CapabilityService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/CapabilityService.kt @@ -18,10 +18,11 @@ * along with this program. If not, see . */ -package com.owncloud.android.lib.resources.status +package com.owncloud.android.lib.resources.status.services import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.Service +import com.owncloud.android.lib.resources.status.RemoteCapability interface CapabilityService: Service { fun getCapabilities() : RemoteOperationResult diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt new file mode 100644 index 00000000..1efa7f1b --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt @@ -0,0 +1,33 @@ +/* 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.status.services + +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.status.OwnCloudVersion + +interface ServerInfoService { + fun checkPathExistence(path: String, isUserLogged: Boolean): RemoteOperationResult + + fun getRemoteStatus(path: String): RemoteOperationResult +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCCapabilityService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCCapabilityService.kt new file mode 100644 index 00000000..d2161b05 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCCapabilityService.kt @@ -0,0 +1,33 @@ +/** + * ownCloud Android client application + * + * @author David González Verdugo + * + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.lib.resources.status.services.implementation + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.status.services.CapabilityService +import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation +import com.owncloud.android.lib.resources.status.RemoteCapability + +class OCCapabilityService(override val client: OwnCloudClient) : + CapabilityService { + override fun getCapabilities(): RemoteOperationResult = + GetRemoteCapabilitiesOperation().execute(client) +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt new file mode 100644 index 00000000..8efd9def --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt @@ -0,0 +1,43 @@ +/** + * ownCloud Android client application + * + * @author Abel García de Prada + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.lib.resources.status.services.implementation + +import android.net.Uri +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.status.services.ServerInfoService +import com.owncloud.android.lib.resources.files.CheckPathExistenceRemoteOperation +import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation +import com.owncloud.android.lib.resources.status.OwnCloudVersion + +class OCServerInfoService : ServerInfoService { + override fun checkPathExistence(path: String, isUserLogged: Boolean): RemoteOperationResult = + CheckPathExistenceRemoteOperation( + remotePath = path, + isUserLogged = true + ).execute(createClientFromPath(path)) + + override fun getRemoteStatus(path: String): RemoteOperationResult = + GetRemoteStatusOperation().execute(createClientFromPath(path)) + + private fun createClientFromPath(path: String): OwnCloudClient { + return OwnCloudClient(Uri.parse(path)) + } +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.java deleted file mode 100644 index dce2096a..00000000 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.java +++ /dev/null @@ -1,111 +0,0 @@ -/* 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.users; - -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 org.json.JSONObject; -import timber.log.Timber; - -import java.net.URL; - -import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; - -/** - * Gets information (id, display name, and e-mail address) about the user logged in. - * - * @author masensio - * @author David A. Velasco - * @author David González Verdugo - */ - -public class GetRemoteUserInfoOperation extends RemoteOperation { - - // OCS Route - private static final String OCS_ROUTE = "/ocs/v2.php/cloud/user?format=json"; - - // JSON Node names - private static final String NODE_OCS = "ocs"; - private static final String NODE_DATA = "data"; - private static final String NODE_ID = "id"; - private static final String NODE_DISPLAY_NAME = "display-name"; - private static final String NODE_EMAIL = "email"; - - public GetRemoteUserInfoOperation() { - } - - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result; - - //Get the user - try { - GetMethod getMethod = new GetMethod(new URL(client.getBaseUri() + OCS_ROUTE)); - - int status = client.executeHttpMethod(getMethod); - - if (isSuccess(status)) { - Timber.d("Successful response"); - - JSONObject respJSON = new JSONObject(getMethod.getResponseBodyAsString()); - JSONObject respOCS = respJSON.getJSONObject(NODE_OCS); - JSONObject respData = respOCS.getJSONObject(NODE_DATA); - - UserInfo userInfo = new UserInfo(); - userInfo.mId = respData.getString(NODE_ID); - userInfo.mDisplayName = respData.getString(NODE_DISPLAY_NAME); - userInfo.mEmail = respData.getString(NODE_EMAIL); - - result = new RemoteOperationResult<>(OK); - - result.setData(userInfo); - - } else { - result = new RemoteOperationResult<>(getMethod); - String response = getMethod.getResponseBodyAsString(); - Timber.e("Failed response while getting user information "); - Timber.e("*** status code: " + status + " ; response message: " + response); - } - } catch (Exception e) { - result = new RemoteOperationResult<>(e); - Timber.e(e, "Exception while getting OC user information"); - } - - return result; - } - - private boolean isSuccess(int status) { - return (status == HttpConstants.HTTP_OK); - } - - public static class UserInfo { - public String mId = ""; - public String mDisplayName = ""; - public String mEmail = ""; - } -} \ No newline at end of file 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 new file mode 100644 index 00000000..54aeb32f --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/GetRemoteUserInfoOperation.kt @@ -0,0 +1,81 @@ +/* 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.users + +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 +import com.owncloud.android.lib.resources.CommonOcsResponse +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import timber.log.Timber +import java.lang.reflect.Type +import java.net.URL + +/** + * Gets information (id, display name, and e-mail address) about the user logged in. + * + * @author masensio + * @author David A. Velasco + * @author David González Verdugo + * @author Abel García de Prada + */ +class GetRemoteUserInfoOperation : RemoteOperation() { + override fun run(client: OwnCloudClient): RemoteOperationResult { + var result: RemoteOperationResult + //Get the user + try { + val getMethod = GetMethod(URL(client.baseUri.toString() + OCS_ROUTE)) + val status = client.executeHttpMethod(getMethod) + val response = getMethod.responseBodyAsString + if (status == HttpConstants.HTTP_OK) { + Timber.d("Successful response $response") + + val moshi: Moshi = Moshi.Builder().build() + val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, UserInfoResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + val commonResponse: CommonOcsResponse? = adapter.fromJson(response) + + result = RemoteOperationResult(ResultCode.OK) + result.data = commonResponse?.ocs?.data?.toRemoteUserInfo() + } else { + result = RemoteOperationResult(getMethod) + Timber.e("Failed response while getting user information status code: $status, response: $response") + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Timber.e(e, "Exception while getting OC user information") + } + return result + } + + companion object { + // OCS Route + private const val OCS_ROUTE = "/ocs/v2.php/cloud/user?format=json" + } +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/RemoteUserInfo.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/RemoteUserInfo.kt new file mode 100644 index 00000000..b66572de --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/RemoteUserInfo.kt @@ -0,0 +1,30 @@ +/* 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.users + +data class RemoteUserInfo( + val id: String, + val displayName: String, + val email: String? +) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/UserInfoResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/UserInfoResponse.kt new file mode 100644 index 00000000..d0fdcf82 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/UserInfoResponse.kt @@ -0,0 +1,42 @@ +/* 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.users + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class UserInfoResponse( + val id: String, + @Json(name = "display-name") + val displayName: String, + val email: String? +) + +fun UserInfoResponse.toRemoteUserInfo() = + RemoteUserInfo( + id = id, + displayName = displayName, + email = email + ) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/UserService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/UserService.kt new file mode 100644 index 00000000..4ef2e1a7 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/UserService.kt @@ -0,0 +1,33 @@ +/* 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.users.services + +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.Service +import com.owncloud.android.lib.resources.users.RemoteUserInfo + +interface UserService: Service { + fun getUserInfo() : RemoteOperationResult +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/implementation/OCUserService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/implementation/OCUserService.kt new file mode 100644 index 00000000..6b07b25e --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/implementation/OCUserService.kt @@ -0,0 +1,32 @@ +/** + * ownCloud Android client application + * + * @author Abel García de Prada + * Copyright (C) 2020 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.lib.resources.users.services.implementation + +import com.owncloud.android.lib.common.OwnCloudClient +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation +import com.owncloud.android.lib.resources.users.RemoteUserInfo +import com.owncloud.android.lib.resources.users.services.UserService + +class OCUserService(override val client: OwnCloudClient) : + UserService { + override fun getUserInfo(): RemoteOperationResult = + GetRemoteUserInfoOperation().execute(client) +}