mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-10 17:36:12 +00:00
commit
8f5f821113
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -19,11 +19,6 @@ gen/
|
||||
# Local configuration files (sdk path, etc)
|
||||
.gradle/
|
||||
local.properties
|
||||
sample_client/local.properties
|
||||
|
||||
# Mac .DS_Store files
|
||||
.DS_Store
|
||||
|
||||
# Proguard README
|
||||
proguard-project.txt
|
||||
sample_client/proguard-project.txt
|
@ -2,7 +2,7 @@
|
||||
|
||||
ownCloud Android Library is available under MIT license
|
||||
|
||||
Copyright (C) 2019 ownCloud GmbH.
|
||||
Copyright (C) 2020 ownCloud GmbH.
|
||||
Copyright (C) 2012 Bartek Przybylski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -1,7 +1,7 @@
|
||||
buildscript {
|
||||
ext {
|
||||
// Libraries
|
||||
kotlinVersion = '1.3.50'
|
||||
kotlinVersion = '1.3.72'
|
||||
moshiVersion = "1.9.2"
|
||||
}
|
||||
|
||||
repositories {
|
||||
@ -9,7 +9,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion"
|
||||
}
|
||||
|
3
gradle.properties
Normal file
3
gradle.properties
Normal file
@ -0,0 +1,3 @@
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536M
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
|
@ -7,7 +7,14 @@ dependencies {
|
||||
api 'com.squareup.okhttp3:okhttp:3.12.0'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||
api 'com.gitlab.ownclouders:dav4android:oc_support_1.0.1'
|
||||
api 'com.github.hannesa2:Logcat:1.5.6'
|
||||
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 {
|
||||
@ -19,11 +26,15 @@ android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
|
||||
versionCode = 10000400
|
||||
versionName = "1.0.4"
|
||||
versionCode = 10000500
|
||||
versionName = "1.0.5"
|
||||
|
||||
// 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 {
|
||||
|
@ -1,63 +0,0 @@
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Dynamic implementation of {@link OwnCloudClientManager}.
|
||||
*
|
||||
* Wraps instances of {@link SingleSessionManager} and {@link SimpleFactoryManager} and delegates on one
|
||||
* or the other depending on the known version of the server corresponding to the {@link OwnCloudAccount}
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
|
||||
public class DynamicSessionManager implements OwnCloudClientManager {
|
||||
|
||||
private SimpleFactoryManager mSimpleFactoryManager = new SimpleFactoryManager();
|
||||
|
||||
private SingleSessionManager mSingleSessionManager = new SingleSessionManager();
|
||||
|
||||
@Override
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
|
||||
throws AccountUtils.AccountNotFoundException,
|
||||
OperationCanceledException, AuthenticatorException, IOException {
|
||||
|
||||
OwnCloudVersion ownCloudVersion = null;
|
||||
if (account.getSavedAccount() != null) {
|
||||
ownCloudVersion = AccountUtils.getServerVersionForAccount(
|
||||
account.getSavedAccount(), context
|
||||
);
|
||||
}
|
||||
|
||||
if (ownCloudVersion != null && ownCloudVersion.isSessionMonitoringSupported()) {
|
||||
return mSingleSessionManager.getClientFor(account, context);
|
||||
} else {
|
||||
return mSimpleFactoryManager.getClientFor(account, context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
OwnCloudClient clientRemovedFromFactoryManager = mSimpleFactoryManager.removeClientFor(account);
|
||||
OwnCloudClient clientRemovedFromSingleSessionManager = mSingleSessionManager.removeClientFor(account);
|
||||
if (clientRemovedFromSingleSessionManager != null) {
|
||||
return clientRemovedFromSingleSessionManager;
|
||||
} else {
|
||||
return clientRemovedFromFactoryManager;
|
||||
}
|
||||
// clientRemoved and clientRemoved2 should not be != null at the same time
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
mSimpleFactoryManager.saveAllClients(context, accountType);
|
||||
mSingleSessionManager.saveAllClients(context, accountType);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -38,12 +38,11 @@ import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.common.utils.RandomUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.HttpUrl;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -54,11 +53,10 @@ 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_UPLOADS_PATH_4_0 = "/remote.php/dav/uploads/";
|
||||
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";
|
||||
public static final String FILES_WEB_PATH = "/index.php/apps/files";
|
||||
|
||||
private static final String TAG = OwnCloudClient.class.getSimpleName();
|
||||
private static final int MAX_REDIRECTIONS_COUNT = 3;
|
||||
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
||||
|
||||
@ -70,13 +68,8 @@ public class OwnCloudClient extends HttpClient {
|
||||
private OwnCloudVersion mVersion = null;
|
||||
private OwnCloudAccount mAccount;
|
||||
|
||||
/**
|
||||
* {@link @OwnCloudClientManager} holding a reference to this object and delivering it to callers; might be
|
||||
* NULL
|
||||
*/
|
||||
private OwnCloudClientManager mOwnCloudClientManager = null;
|
||||
private SingleSessionManager mSingleSessionManager = null;
|
||||
|
||||
private String mRedirectedLocation;
|
||||
private boolean mFollowRedirects;
|
||||
|
||||
public OwnCloudClient(Uri baseUri) {
|
||||
@ -86,7 +79,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
mBaseUri = baseUri;
|
||||
|
||||
mInstanceNumber = sIntanceCounter++;
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
|
||||
Timber.d("#" + mInstanceNumber + "Creating OwnCloudClient");
|
||||
|
||||
clearCredentials();
|
||||
clearCookies();
|
||||
@ -99,7 +92,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
mCredentials.applyTo(this);
|
||||
}
|
||||
|
||||
public void applyCredentials() {
|
||||
void applyCredentials() {
|
||||
mCredentials.applyTo(this);
|
||||
}
|
||||
|
||||
@ -112,7 +105,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
setRequestId(method);
|
||||
|
||||
status = method.execute();
|
||||
checkFirstRedirection(method);
|
||||
|
||||
if (mFollowRedirects) {
|
||||
status = followRedirection(method).getLastStatus();
|
||||
@ -127,13 +119,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
return status;
|
||||
}
|
||||
|
||||
private void checkFirstRedirection(HttpBaseMethod method) {
|
||||
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||
if (location != null && !location.isEmpty()) {
|
||||
mRedirectedLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
private int executeRedirectedHttpMethod(HttpBaseMethod method) throws Exception {
|
||||
boolean repeatWithFreshCredentials;
|
||||
int repeatCounter = 0;
|
||||
@ -163,7 +148,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
// Header to allow tracing requests in apache and ownCloud logs
|
||||
addHeaderForAllRequests(OC_X_REQUEST_ID, requestId);
|
||||
|
||||
Log_OC.d(TAG, "Executing " + method.getClass().getSimpleName() + " in request with id " + requestId);
|
||||
Timber.d("Executing in request with id %s", requestId);
|
||||
}
|
||||
|
||||
public RedirectionPath followRedirection(HttpBaseMethod method) throws Exception {
|
||||
@ -175,15 +160,14 @@ public class OwnCloudClient extends HttpClient {
|
||||
(status == HttpConstants.HTTP_MOVED_PERMANENTLY ||
|
||||
status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
||||
status == HttpConstants.HTTP_TEMPORARY_REDIRECT)
|
||||
) {
|
||||
) {
|
||||
|
||||
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null
|
||||
? method.getResponseHeader(HttpConstants.LOCATION_HEADER)
|
||||
: method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||
|
||||
if (location != null) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Location to redirect: " + location);
|
||||
Timber.d("#" + mInstanceNumber + "Location to redirect: " + location);
|
||||
|
||||
redirectionPath.addLocation(location);
|
||||
|
||||
@ -216,7 +200,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
redirectionsCount++;
|
||||
|
||||
} else {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No location to redirect!");
|
||||
Timber.d(" #" + mInstanceNumber + "No location to redirect!");
|
||||
status = HttpConstants.HTTP_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
@ -237,8 +221,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
responseBodyAsStream.close();
|
||||
|
||||
} catch (IOException io) {
|
||||
Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response;" +
|
||||
" will be IGNORED", io);
|
||||
Timber.e(io, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -248,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()
|
||||
@ -296,38 +279,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void logCookie(Cookie cookie) {
|
||||
Log_OC.d(TAG, "Cookie name: " + cookie.name());
|
||||
Log_OC.d(TAG, " value: " + cookie.value());
|
||||
Log_OC.d(TAG, " domain: " + cookie.domain());
|
||||
Log_OC.d(TAG, " path: " + cookie.path());
|
||||
Log_OC.d(TAG, " expiryDate: " + cookie.expiresAt());
|
||||
Log_OC.d(TAG, " secure: " + cookie.secure());
|
||||
}
|
||||
|
||||
private void logCookiesAtRequest(Headers headers, String when) {
|
||||
int counter = 0;
|
||||
for (final String cookieHeader : headers.toMultimap().get("cookie")) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Cookies at request (" + when + ") (" + counter++ + "): "
|
||||
+ cookieHeader);
|
||||
}
|
||||
if (counter == 0) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No cookie at request before");
|
||||
}
|
||||
}
|
||||
|
||||
private void logSetCookiesAtResponse(Headers headers) {
|
||||
int counter = 0;
|
||||
for (final String cookieHeader : headers.toMultimap().get("set-cookie")) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Set-Cookie (" + counter++ + "): " + cookieHeader);
|
||||
}
|
||||
if (counter == 0) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No set-cookie");
|
||||
}
|
||||
}
|
||||
|
||||
public String getCookiesString() {
|
||||
StringBuilder cookiesString = new StringBuilder();
|
||||
List<Cookie> cookieList = getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()));
|
||||
@ -384,7 +335,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
if (invalidated) {
|
||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||
|
||||
try {
|
||||
mAccount.loadCredentials(getContext());
|
||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||
@ -392,18 +342,16 @@ public class OwnCloudClient extends HttpClient {
|
||||
credentialsWereRefreshed = true;
|
||||
|
||||
} catch (AccountsException | IOException e) {
|
||||
Log_OC.e(
|
||||
TAG,
|
||||
"Error while trying to refresh auth token for " + mAccount.getSavedAccount().name,
|
||||
e
|
||||
Timber.e(e, "Error while trying to refresh auth token for %s",
|
||||
mAccount.getSavedAccount().name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!credentialsWereRefreshed && mOwnCloudClientManager != null) {
|
||||
if (!credentialsWereRefreshed && mSingleSessionManager != null) {
|
||||
// if credentials are not refreshed, client must be removed
|
||||
// from the OwnCloudClientManager to prevent it is reused once and again
|
||||
mOwnCloudClientManager.removeClientFor(mAccount);
|
||||
mSingleSessionManager.removeClientFor(mAccount);
|
||||
}
|
||||
}
|
||||
// else: onExecute will finish with status 401
|
||||
@ -421,21 +369,21 @@ public class OwnCloudClient extends HttpClient {
|
||||
* cannot be invalidated with the given arguments.
|
||||
*/
|
||||
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
||||
boolean shouldInvalidateAccountCredentials =
|
||||
(httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED);
|
||||
|
||||
boolean should = (httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED); // invalid credentials
|
||||
|
||||
should &= (mCredentials != null && // real credentials
|
||||
shouldInvalidateAccountCredentials &= (mCredentials != null && // real credentials
|
||||
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
||||
|
||||
// test if have all the needed to effectively invalidate ...
|
||||
should &= (mAccount != null && mAccount.getSavedAccount() != null && getContext() != null);
|
||||
shouldInvalidateAccountCredentials &= (mAccount != null && mAccount.getSavedAccount() != null && getContext() != null);
|
||||
|
||||
return should;
|
||||
return shouldInvalidateAccountCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates credentials stored for the given account in the system {@link AccountManager} and in
|
||||
* current {@link OwnCloudClientManagerFactory#getDefaultSingleton()} instance.
|
||||
* current {@link SingleSessionManager#getDefaultSingleton()} instance.
|
||||
* <p>
|
||||
* {@link #shouldInvalidateAccountCredentials(int)} should be called first.
|
||||
*
|
||||
@ -451,14 +399,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
return true;
|
||||
}
|
||||
|
||||
public OwnCloudClientManager getOwnCloudClientManager() {
|
||||
return mOwnCloudClientManager;
|
||||
}
|
||||
|
||||
void setOwnCloudClientManager(OwnCloudClientManager clientManager) {
|
||||
mOwnCloudClientManager = clientManager;
|
||||
}
|
||||
|
||||
public boolean followRedirects() {
|
||||
return mFollowRedirects;
|
||||
}
|
||||
@ -466,4 +406,4 @@ public class OwnCloudClient extends HttpClient {
|
||||
public void setFollowRedirects(boolean followRedirects) {
|
||||
this.mFollowRedirects = followRedirects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -29,8 +29,6 @@ import android.net.Uri;
|
||||
|
||||
public class OwnCloudClientFactory {
|
||||
|
||||
final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Creates a OwnCloudClient to access a URL and sets the desired parameters for ownCloud
|
||||
* client connections.
|
||||
@ -39,8 +37,7 @@ public class OwnCloudClientFactory {
|
||||
* @param context Android context where the OwnCloudClient is being created.
|
||||
* @return A OwnCloudClient object ready to be used
|
||||
*/
|
||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
||||
boolean followRedirects) {
|
||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
|
||||
OwnCloudClient client = new OwnCloudClient(uri);
|
||||
|
||||
client.setFollowRedirects(followRedirects);
|
||||
@ -49,4 +46,4 @@ public class OwnCloudClientFactory {
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
public class OwnCloudClientManagerFactory {
|
||||
|
||||
private static Policy sDefaultPolicy = Policy.ALWAYS_NEW_CLIENT;
|
||||
private static OwnCloudClientManager sDefaultSingleton;
|
||||
private static String sUserAgent;
|
||||
|
||||
public static OwnCloudClientManager newDefaultOwnCloudClientManager() {
|
||||
return newOwnCloudClientManager(sDefaultPolicy);
|
||||
}
|
||||
|
||||
public static OwnCloudClientManager newOwnCloudClientManager(Policy policy) {
|
||||
switch (policy) {
|
||||
case ALWAYS_NEW_CLIENT:
|
||||
return new SimpleFactoryManager();
|
||||
|
||||
case SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING:
|
||||
return new DynamicSessionManager();
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown policy");
|
||||
}
|
||||
}
|
||||
|
||||
public static OwnCloudClientManager getDefaultSingleton() {
|
||||
if (sDefaultSingleton == null) {
|
||||
sDefaultSingleton = newDefaultOwnCloudClientManager();
|
||||
}
|
||||
return sDefaultSingleton;
|
||||
}
|
||||
|
||||
public static Policy getDefaultPolicy() {
|
||||
return sDefaultPolicy;
|
||||
}
|
||||
|
||||
public static void setDefaultPolicy(Policy policy) {
|
||||
if (policy == null) {
|
||||
throw new IllegalArgumentException("Default policy cannot be NULL");
|
||||
}
|
||||
if (defaultSingletonMustBeUpdated(policy)) {
|
||||
sDefaultSingleton = null;
|
||||
}
|
||||
sDefaultPolicy = policy;
|
||||
}
|
||||
|
||||
public static String getUserAgent() {
|
||||
return sUserAgent;
|
||||
}
|
||||
|
||||
public static void setUserAgent(String userAgent) {
|
||||
sUserAgent = userAgent;
|
||||
}
|
||||
|
||||
private static boolean defaultSingletonMustBeUpdated(Policy policy) {
|
||||
if (sDefaultSingleton == null) {
|
||||
return false;
|
||||
}
|
||||
return policy == Policy.ALWAYS_NEW_CLIENT && !(sDefaultSingleton instanceof SimpleFactoryManager);
|
||||
}
|
||||
|
||||
public enum Policy {
|
||||
ALWAYS_NEW_CLIENT,
|
||||
SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SimpleFactoryManager implements OwnCloudClientManager {
|
||||
|
||||
private static final String TAG = SimpleFactoryManager.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws
|
||||
OperationCanceledException, AuthenticatorException, IOException {
|
||||
|
||||
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
|
||||
|
||||
OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(
|
||||
account.getBaseUri(),
|
||||
context.getApplicationContext(),
|
||||
true);
|
||||
|
||||
Log_OC.v(TAG, " new client {" +
|
||||
(account.getName() != null ?
|
||||
account.getName() :
|
||||
AccountUtils.buildAccountName(account.getBaseUri(), "")
|
||||
|
||||
) + ", " + client.hashCode() + "}");
|
||||
|
||||
if (account.getCredentials() == null) {
|
||||
account.loadCredentials(context);
|
||||
}
|
||||
client.setCredentials(account.getCredentials());
|
||||
client.setAccount(account);
|
||||
client.setContext(context);
|
||||
client.setOwnCloudClientManager(this);
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
// nothing to do - not taking care of tracking instances!
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
// nothing to do - not taking care of tracking instances!
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -30,11 +30,10 @@ import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
@ -42,31 +41,39 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OwnCloudClientManager}
|
||||
* <p>
|
||||
* TODO check multithreading safety
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author Christian Schabesberger
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class SingleSessionManager implements OwnCloudClientManager {
|
||||
public class SingleSessionManager {
|
||||
|
||||
private static final String TAG = SingleSessionManager.class.getSimpleName();
|
||||
private static SingleSessionManager sDefaultSingleton;
|
||||
private static String sUserAgent;
|
||||
|
||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername = new ConcurrentHashMap<>();
|
||||
|
||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public static SingleSessionManager getDefaultSingleton() {
|
||||
if (sDefaultSingleton == null) {
|
||||
sDefaultSingleton = new SingleSessionManager();
|
||||
}
|
||||
return sDefaultSingleton;
|
||||
}
|
||||
|
||||
public static String getUserAgent() {
|
||||
return sUserAgent;
|
||||
}
|
||||
|
||||
public static void setUserAgent(String userAgent) {
|
||||
sUserAgent = userAgent;
|
||||
}
|
||||
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
|
||||
AuthenticatorException, IOException {
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "getClientFor starting ");
|
||||
}
|
||||
Timber.d("getClientFor starting ");
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account");
|
||||
}
|
||||
@ -84,21 +91,16 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
||||
if (accountName != null) {
|
||||
client = mClientsWithUnknownUsername.remove(sessionName);
|
||||
if (client != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
||||
}
|
||||
Timber.v("reusing client for session %s", sessionName);
|
||||
|
||||
mClientsWithKnownUsername.put(accountName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "moved client to account " + accountName);
|
||||
}
|
||||
Timber.v("moved client to account %s", accountName);
|
||||
}
|
||||
} else {
|
||||
client = mClientsWithUnknownUsername.get(sessionName);
|
||||
}
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for account " + accountName);
|
||||
}
|
||||
Timber.v("reusing client for account %s", accountName);
|
||||
reusingKnown = true;
|
||||
}
|
||||
|
||||
@ -110,47 +112,36 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
||||
true); // TODO remove dependency on OwnCloudClientFactory
|
||||
client.setAccount(account);
|
||||
HttpClient.setContext(context);
|
||||
client.setOwnCloudClientManager(this);
|
||||
|
||||
account.loadCredentials(context);
|
||||
client.setCredentials(account.getCredentials());
|
||||
|
||||
if (accountName != null) {
|
||||
mClientsWithKnownUsername.put(accountName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "new client for account " + accountName);
|
||||
}
|
||||
Timber.v("new client for account %s", accountName);
|
||||
|
||||
} else {
|
||||
mClientsWithUnknownUsername.put(sessionName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "new client for session " + sessionName);
|
||||
}
|
||||
Timber.v("new client for session %s", sessionName);
|
||||
}
|
||||
} else {
|
||||
if (!reusingKnown && Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
||||
if (!reusingKnown) {
|
||||
Timber.v("reusing client for session %s", sessionName);
|
||||
}
|
||||
|
||||
keepCredentialsUpdated(client);
|
||||
keepCookiesUpdated(context, account, client);
|
||||
keepUriUpdated(account, client);
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "getClientFor finishing ");
|
||||
}
|
||||
Timber.d("getClientFor finishing ");
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "removeClientFor starting ");
|
||||
}
|
||||
public void removeClientFor(OwnCloudAccount account) {
|
||||
Timber.d("removeClientFor starting ");
|
||||
|
||||
if (account == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
OwnCloudClient client;
|
||||
@ -158,31 +149,20 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
||||
if (accountName != null) {
|
||||
client = mClientsWithKnownUsername.remove(accountName);
|
||||
if (client != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "Removed client for account " + accountName);
|
||||
}
|
||||
return client;
|
||||
Timber.v("Removed client for account %s", accountName);
|
||||
return;
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "No client tracked for account " + accountName);
|
||||
}
|
||||
Timber.v("No client tracked for account %s", accountName);
|
||||
}
|
||||
}
|
||||
|
||||
mClientsWithUnknownUsername.clear();
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "removeClientFor finishing ");
|
||||
}
|
||||
return null;
|
||||
Timber.d("removeClientFor finishing ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "Saving sessions... ");
|
||||
}
|
||||
Timber.d("Saving sessions... ");
|
||||
|
||||
Iterator<String> accountNames = mClientsWithKnownUsername.keySet().iterator();
|
||||
String accountName;
|
||||
@ -193,9 +173,7 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
||||
AccountUtils.saveClient(mClientsWithKnownUsername.get(accountName), account, context);
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "All sessions saved");
|
||||
}
|
||||
Timber.d("All sessions saved");
|
||||
}
|
||||
|
||||
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -36,19 +36,16 @@ import android.net.Uri;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import okhttp3.Cookie;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AccountUtils {
|
||||
|
||||
private static final String TAG = AccountUtils.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Constructs full url to host and webdav resource basing on host version
|
||||
*
|
||||
@ -66,7 +63,7 @@ public class AccountUtils {
|
||||
webDavUrlForAccount = getBaseUrlForAccount(context, account) + OwnCloudClient.WEBDAV_FILES_PATH_4_0
|
||||
+ ownCloudCredentials.getUsername();
|
||||
} catch (OperationCanceledException | AuthenticatorException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Timber.e(e);
|
||||
}
|
||||
|
||||
return webDavUrlForAccount;
|
||||
@ -104,7 +101,7 @@ public class AccountUtils {
|
||||
try {
|
||||
username = account.name.substring(0, account.name.lastIndexOf('@'));
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Couldn't get a username for the given account", e);
|
||||
Timber.e(e, "Couldn't get a username for the given account");
|
||||
}
|
||||
return username;
|
||||
}
|
||||
@ -124,7 +121,7 @@ public class AccountUtils {
|
||||
version = new OwnCloudVersion(versionString);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Couldn't get a the server version for an account", e);
|
||||
Timber.e(e, "Couldn't get a the server version for an account");
|
||||
}
|
||||
return version;
|
||||
}
|
||||
@ -142,10 +139,9 @@ 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);
|
||||
OwnCloudVersion version = new OwnCloudVersion(am.getUserData(account, Constants.KEY_OC_VERSION));
|
||||
|
||||
if (isOauth2) {
|
||||
String accessToken = am.blockingGetAuthToken(
|
||||
@ -154,7 +150,6 @@ public class AccountUtils {
|
||||
false);
|
||||
|
||||
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
|
||||
|
||||
} else {
|
||||
String password = am.blockingGetAuthToken(
|
||||
account,
|
||||
@ -163,8 +158,7 @@ public class AccountUtils {
|
||||
|
||||
credentials = OwnCloudCredentialsFactory.newBasicCredentials(
|
||||
username,
|
||||
password,
|
||||
version.isPreemptiveAuthenticationPreferred()
|
||||
password
|
||||
);
|
||||
}
|
||||
|
||||
@ -203,9 +197,8 @@ public class AccountUtils {
|
||||
if (url.contains("://")) {
|
||||
url = url.substring(serverBaseUrl.toString().indexOf("://") + 3);
|
||||
}
|
||||
String accountName = username + "@" + url;
|
||||
|
||||
return accountName;
|
||||
return username + "@" + url;
|
||||
}
|
||||
|
||||
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
||||
@ -216,7 +209,7 @@ public class AccountUtils {
|
||||
String cookiesString = client.getCookiesString();
|
||||
if (!"".equals(cookiesString)) {
|
||||
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
|
||||
Log_OC.d(TAG, "Saving Cookies: " + cookiesString);
|
||||
Timber.d("Saving Cookies: %s", cookiesString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,10 +223,10 @@ public class AccountUtils {
|
||||
*/
|
||||
public static void restoreCookies(Account account, OwnCloudClient client, Context context) {
|
||||
if (account == null) {
|
||||
Log_OC.d(TAG, "Cannot restore cookie for null account");
|
||||
Timber.d("Cannot restore cookie for null account");
|
||||
|
||||
} else {
|
||||
Log_OC.d(TAG, "Restoring cookies for " + account.name);
|
||||
Timber.d("Restoring cookies for %s", account.name);
|
||||
|
||||
// Account Manager
|
||||
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||
@ -299,8 +292,12 @@ public class AccountUtils {
|
||||
/**
|
||||
* Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
|
||||
*/
|
||||
|
||||
// TODO Please review this constants, move them out of the library, the rest of OAuth variables are in data layer
|
||||
public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
|
||||
|
||||
public static final String OAUTH_SUPPORTED_TRUE = "TRUE";
|
||||
|
||||
/**
|
||||
* OC account cookies
|
||||
*/
|
||||
@ -321,9 +318,6 @@ public class AccountUtils {
|
||||
*/
|
||||
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
||||
|
||||
/**
|
||||
* OAuth2 refresh token
|
||||
**/
|
||||
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
||||
public static final int ACCOUNT_VERSION = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -31,8 +31,6 @@ import okhttp3.internal.Util;
|
||||
|
||||
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
||||
|
||||
private static final String TAG = OwnCloudCredentials.class.getSimpleName();
|
||||
|
||||
private String mUsername;
|
||||
private String mPassword;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -38,12 +38,6 @@ public class OwnCloudCredentialsFactory {
|
||||
return new OwnCloudBasicCredentials(username, password);
|
||||
}
|
||||
|
||||
public static OwnCloudCredentials newBasicCredentials(
|
||||
String username, String password, boolean preemptiveMode
|
||||
) {
|
||||
return new OwnCloudBasicCredentials(username, password, preemptiveMode);
|
||||
}
|
||||
|
||||
public static OwnCloudCredentials newBearerCredentials(String username, String authToken) {
|
||||
return new OwnCloudBearerCredentials(username, authToken);
|
||||
}
|
||||
|
@ -1,95 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 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.authentication.oauth;
|
||||
|
||||
/**
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
public class BearerCredentials {
|
||||
|
||||
public static final int HASH_SEED = 17;
|
||||
public static final int HASH_OFFSET = 37;
|
||||
|
||||
private String mAccessToken;
|
||||
|
||||
/**
|
||||
* The constructor with the bearer token
|
||||
*
|
||||
* @param token The bearer token
|
||||
*/
|
||||
public BearerCredentials(String token) {
|
||||
mAccessToken = (token == null) ? "" : token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access token
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String getAccessToken() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this object string.
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String toString() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a hash of the access token.
|
||||
*
|
||||
* @return The hash code of the access token
|
||||
*/
|
||||
public int hashCode() {
|
||||
return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* These credentials are assumed equal if accessToken is the same.
|
||||
*
|
||||
* @param o The other object to compare with.
|
||||
* @return 'True' if the object is equivalent.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (this.getClass().equals(o.getClass())) {
|
||||
BearerCredentials that = (BearerCredentials) o;
|
||||
if (mAccessToken.equals(that.mAccessToken)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
/**
|
||||
* Constant values for OAuth 2 protocol.
|
||||
* <p>
|
||||
* Includes required and optional parameter NAMES used in the 'authorization code' grant type.
|
||||
*/
|
||||
|
||||
public class OAuth2Constants {
|
||||
|
||||
/// Parameters to send to the Authorization Endpoint
|
||||
public static final String KEY_RESPONSE_TYPE = "response_type";
|
||||
public static final String KEY_REDIRECT_URI = "redirect_uri";
|
||||
public static final String KEY_CLIENT_ID = "client_id";
|
||||
public static final String KEY_SCOPE = "scope";
|
||||
public static final String KEY_STATE = "state";
|
||||
|
||||
/// Additional parameters to send to the Token Endpoint
|
||||
public static final String KEY_GRANT_TYPE = "grant_type";
|
||||
public static final String KEY_CODE = "code";
|
||||
|
||||
// Used to get the Access Token using Refresh Token
|
||||
public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
|
||||
|
||||
/// Parameters received in an OK response from the Token Endpoint
|
||||
public static final String KEY_ACCESS_TOKEN = "access_token";
|
||||
public static final String KEY_TOKEN_TYPE = "token_type";
|
||||
public static final String KEY_EXPIRES_IN = "expires_in";
|
||||
public static final String KEY_REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
/// Parameters in an ERROR response
|
||||
public static final String KEY_ERROR = "error";
|
||||
public static final String KEY_ERROR_DESCRIPTION = "error_description";
|
||||
public static final String KEY_ERROR_URI = "error_uri";
|
||||
public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
|
||||
|
||||
/// Extra not standard
|
||||
public static final String KEY_USER_ID = "user_id";
|
||||
|
||||
/// Depends on oauth2 grant type
|
||||
public static final String OAUTH2_RESPONSE_TYPE_CODE = "code";
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2019 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.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
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 okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private final String mAccessTokenEndpointPath;
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
private String mGrantType;
|
||||
private String mCode;
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRedirectUri;
|
||||
|
||||
public OAuth2GetAccessTokenOperation(
|
||||
String grantType,
|
||||
String code,
|
||||
String clientId,
|
||||
String secretId,
|
||||
String redirectUri,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRedirectUri = redirectUri;
|
||||
mGrantType = grantType;
|
||||
mCode = code;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult<Map<String, String>> result = null;
|
||||
|
||||
try {
|
||||
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE, mGrantType)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CODE, mCode)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
OwnCloudCredentials oauthCredentials =
|
||||
new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
String response = postMethod.getResponseBodyAsString();
|
||||
if (response != null && response.length() > 0) {
|
||||
JSONObject tokenJson = new JSONObject(response);
|
||||
Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||
result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR);
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
public interface OAuth2Provider {
|
||||
|
||||
/**
|
||||
* {@link OAuth2RequestBuilder} implementation for this provider.
|
||||
*
|
||||
* @return {@link OAuth2RequestBuilder} implementation.
|
||||
*/
|
||||
OAuth2RequestBuilder getOperationBuilder();
|
||||
|
||||
/**
|
||||
* Configuration of the client that is using this {@link OAuth2Provider}
|
||||
* return Configuration of the client that is usinng this {@link OAuth2Provider}
|
||||
*/
|
||||
OAuth2ClientConfiguration getClientConfiguration();
|
||||
|
||||
/**
|
||||
* Set configuration of the client that will use this {@link OAuth2Provider}
|
||||
*
|
||||
* @param oAuth2ClientConfiguration Configuration of the client that will use this {@link OAuth2Provider}
|
||||
*/
|
||||
void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration);
|
||||
|
||||
/**
|
||||
* base URI to authorization server.
|
||||
*
|
||||
* @return Base URL to authorization server.
|
||||
*/
|
||||
String getAuthorizationServerUri();
|
||||
|
||||
/**
|
||||
* Set base URI to authorization server.
|
||||
*
|
||||
* @param authorizationServerUri Set base URL to authorization server.
|
||||
*/
|
||||
void setAuthorizationServerUri(String authorizationServerUri);
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2ProvidersRegistry {
|
||||
|
||||
private Map<String, OAuth2Provider> mProviders = new HashMap<>();
|
||||
|
||||
private OAuth2Provider mDefaultProvider = null;
|
||||
|
||||
private OAuth2ProvidersRegistry() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton accesor.
|
||||
*
|
||||
* @return Singleton isntance of {@link OAuth2ProvidersRegistry}
|
||||
*/
|
||||
public static OAuth2ProvidersRegistry getInstance() {
|
||||
return LazyHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@link OAuth2Provider} with the name passed as parameter.
|
||||
*
|
||||
* @param name Name to bind 'oAuthProvider' in the registry.
|
||||
* @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry.
|
||||
* @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null.
|
||||
*/
|
||||
public void registerProvider(String name, OAuth2Provider oAuth2Provider) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name must not be NULL");
|
||||
}
|
||||
if (oAuth2Provider == null) {
|
||||
throw new IllegalArgumentException("oAuth2Provider must not be NULL");
|
||||
}
|
||||
|
||||
mProviders.put(name, oAuth2Provider);
|
||||
if (mProviders.size() == 1) {
|
||||
mDefaultProvider = oAuth2Provider;
|
||||
}
|
||||
}
|
||||
|
||||
public OAuth2Provider unregisterProvider(String name) {
|
||||
OAuth2Provider unregisteredProvider = mProviders.remove(name);
|
||||
if (mProviders.size() == 0) {
|
||||
mDefaultProvider = null;
|
||||
} else if (unregisteredProvider != null && unregisteredProvider == mDefaultProvider) {
|
||||
mDefaultProvider = mProviders.values().iterator().next();
|
||||
}
|
||||
return unregisteredProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default {@link OAuth2Provider}.
|
||||
*
|
||||
* @return Default provider, or NULL if there is no provider.
|
||||
*/
|
||||
public OAuth2Provider getProvider() {
|
||||
return mDefaultProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link OAuth2Provider} registered with the name passed as parameter.
|
||||
*
|
||||
* @param name Name used to register the desired {@link OAuth2Provider}
|
||||
* @return {@link OAuth2Provider} registered with the name 'name'
|
||||
*/
|
||||
public OAuth2Provider getProvider(String name) {
|
||||
return mProviders.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2Provider} registered with the name passed as parameter as the default provider
|
||||
*
|
||||
* @param name Name used to register the {@link OAuth2Provider} to set as default.
|
||||
* @return {@link OAuth2Provider} set as default, or NULL if no provider was registered with 'name'.
|
||||
*/
|
||||
public OAuth2Provider setDefaultProvider(String name) {
|
||||
OAuth2Provider toDefault = mProviders.get(name);
|
||||
if (toDefault != null) {
|
||||
mDefaultProvider = toDefault;
|
||||
}
|
||||
return toDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
|
||||
*/
|
||||
private static class LazyHolder {
|
||||
private static final OAuth2ProvidersRegistry INSTANCE = new OAuth2ProvidersRegistry();
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2QueryParser {
|
||||
|
||||
private static final String TAG = OAuth2QueryParser.class.getName();
|
||||
|
||||
private Map<String, String> mOAuth2ParsedAuthorizationResponse;
|
||||
|
||||
public OAuth2QueryParser() {
|
||||
mOAuth2ParsedAuthorizationResponse = new HashMap<>();
|
||||
}
|
||||
|
||||
public Map<String, String> parse(String query) {
|
||||
mOAuth2ParsedAuthorizationResponse.clear();
|
||||
|
||||
if (query != null) {
|
||||
String[] pairs = query.split("&");
|
||||
int i = 0;
|
||||
String key = "";
|
||||
String value;
|
||||
while (pairs.length > i) {
|
||||
int j = 0;
|
||||
String[] part = pairs[i].split("=");
|
||||
while (part.length > j) {
|
||||
String p = part[j];
|
||||
if (j == 0) {
|
||||
key = p;
|
||||
} else if (j == 1) {
|
||||
value = p;
|
||||
mOAuth2ParsedAuthorizationResponse.put(key, value);
|
||||
}
|
||||
|
||||
Log_OC.v(TAG, "[" + i + "," + j + "] = " + p);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return mOAuth2ParsedAuthorizationResponse;
|
||||
}
|
||||
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David González Verdugo
|
||||
* @author Christian Schabesberger
|
||||
* <p>
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
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.common.utils.Log_OC;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
|
||||
private final String mAccessTokenEndpointPath;
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRefreshToken;
|
||||
|
||||
public OAuth2RefreshAccessTokenOperation(
|
||||
String clientId,
|
||||
String secretId,
|
||||
String refreshToken,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRefreshToken = refreshToken;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<Map<String, String>> run(OwnCloudClient client) {
|
||||
|
||||
try {
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE,
|
||||
OAuth2GrantType.REFRESH_TOKEN.getValue())
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
final OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
|
||||
final OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
final String responseData = postMethod.getResponseBodyAsString();
|
||||
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + responseData);
|
||||
|
||||
if (responseData != null && responseData.length() > 0) {
|
||||
final JSONObject tokenJson = new JSONObject(responseData);
|
||||
|
||||
final Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
|
||||
final RemoteOperationResult<Map<String, String>> result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
return (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null)
|
||||
? new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR)
|
||||
: result;
|
||||
} else {
|
||||
return new RemoteOperationResult<>(postMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return new RemoteOperationResult<>(e);
|
||||
}
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* <p>
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class OAuth2ResponseParser {
|
||||
|
||||
Map<String, String> parseAccessTokenResult(JSONObject tokenJson) throws JSONException {
|
||||
Map<String, String> resultTokenMap = new HashMap<>();
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ACCESS_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_TOKEN_TYPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_EXPIRES_IN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_REFRESH_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_SCOPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_URI));
|
||||
}
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard
|
||||
resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson.
|
||||
getString(OAuth2Constants.KEY_USER_ID));
|
||||
}
|
||||
|
||||
return resultTokenMap;
|
||||
}
|
||||
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
public class OwnCloudOAuth2Provider implements OAuth2Provider {
|
||||
|
||||
public static final String NAME = OAuth2Provider.class.getName();
|
||||
|
||||
public static final String ACCESS_TOKEN_ENDPOINT_PATH = "index.php/apps/oauth2/api/v1/token";
|
||||
private static final String AUTHORIZATION_CODE_ENDPOINT_PATH = "index.php/apps/oauth2/authorize";
|
||||
|
||||
private String mAuthorizationServerUrl = "";
|
||||
private String mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
private String mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
|
||||
private OAuth2ClientConfiguration mClientConfiguration;
|
||||
|
||||
@Override
|
||||
public OAuth2RequestBuilder getOperationBuilder() {
|
||||
return new OwnCloudOAuth2RequestBuilder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2ClientConfiguration getClientConfiguration() {
|
||||
return mClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
|
||||
mClientConfiguration = oAuth2ClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationServerUri() {
|
||||
return mAuthorizationServerUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationServerUri(String authorizationServerUri) {
|
||||
mAuthorizationServerUrl = authorizationServerUri;
|
||||
}
|
||||
|
||||
public String getAccessTokenEndpointPath() {
|
||||
return mAccessTokenEndpointPath;
|
||||
}
|
||||
|
||||
public void setAccessTokenEndpointPath(String accessTokenEndpointPath) {
|
||||
if (accessTokenEndpointPath == null || accessTokenEndpointPath.length() <= 0) {
|
||||
Log_OC.w(NAME, "Setting invalid access token endpoint path, going on with default");
|
||||
mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAccessTokenEndpointPath = accessTokenEndpointPath;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthorizationCodeEndpointPath() {
|
||||
return mAuthorizationCodeEndpointPath;
|
||||
}
|
||||
|
||||
public void setAuthorizationCodeEndpointPath(String authorizationCodeEndpointPath) {
|
||||
if (authorizationCodeEndpointPath == null || authorizationCodeEndpointPath.length() <= 0) {
|
||||
Log_OC.w(NAME, "Setting invalid authorization code endpoint path, going on with default");
|
||||
mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAuthorizationCodeEndpointPath = authorizationCodeEndpointPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 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.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
|
||||
public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
|
||||
|
||||
private OwnCloudOAuth2Provider mOAuth2Provider;
|
||||
|
||||
private OAuthRequest mRequest;
|
||||
private OAuth2GrantType mGrantType = OAuth2GrantType.AUTHORIZATION_CODE;
|
||||
private String mCode;
|
||||
private String mRefreshToken;
|
||||
|
||||
public OwnCloudOAuth2RequestBuilder(OwnCloudOAuth2Provider ownCloudOAuth2Provider) {
|
||||
mOAuth2Provider = ownCloudOAuth2Provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequest(OAuthRequest request) {
|
||||
mRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGrantType(OAuth2GrantType grantType) {
|
||||
mGrantType = grantType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationCode(String code) {
|
||||
mCode = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
mRefreshToken = refreshToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteOperation buildOperation() {
|
||||
if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE &&
|
||||
mGrantType != OAuth2GrantType.REFRESH_TOKEN) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " +
|
||||
OAuth2GrantType.REFRESH_TOKEN + " are supported"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
|
||||
switch (mRequest) {
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
return new OAuth2GetAccessTokenOperation(
|
||||
mGrantType.getValue(),
|
||||
mCode,
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
clientConfiguration.getRedirectUri(),
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
|
||||
case REFRESH_ACCESS_TOKEN:
|
||||
return new OAuth2RefreshAccessTokenOperation(
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
mRefreshToken,
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildUri() {
|
||||
if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
Uri uri;
|
||||
Uri.Builder uriBuilder;
|
||||
switch (mRequest) {
|
||||
case GET_AUTHORIZATION_CODE:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -26,18 +26,17 @@ package com.owncloud.android.lib.common.http;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import android.os.Build;
|
||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||
import com.owncloud.android.lib.common.SingleSessionManager;
|
||||
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
|
||||
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
|
||||
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
import timber.log.Timber;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
@ -58,8 +57,6 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class HttpClient {
|
||||
private static final String TAG = HttpClient.class.toString();
|
||||
|
||||
private static OkHttpClient sOkHttpClient;
|
||||
private static HttpInterceptor sOkHttpInterceptor;
|
||||
private static Context sContext;
|
||||
@ -77,10 +74,10 @@ public class HttpClient {
|
||||
sslContext = SSLContext.getInstance("TLSv1.2");
|
||||
} catch (NoSuchAlgorithmException tlsv12Exception) {
|
||||
try {
|
||||
Log_OC.w(TAG, "TLSv1.2 is not supported in this device; falling through TLSv1.1");
|
||||
Timber.w("TLSv1.2 is not supported in this device; falling through TLSv1.1");
|
||||
sslContext = SSLContext.getInstance("TLSv1.1");
|
||||
} catch (NoSuchAlgorithmException tlsv11Exception) {
|
||||
Log_OC.w(TAG, "TLSv1.1 is not supported in this device; falling through TLSv1.0");
|
||||
Timber.w("TLSv1.1 is not supported in this device; falling through TLSv1.0");
|
||||
sslContext = SSLContext.getInstance("TLSv1");
|
||||
// should be available in any device; see reference of supported protocols in
|
||||
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
||||
@ -91,22 +88,15 @@ public class HttpClient {
|
||||
|
||||
SSLSocketFactory sslSocketFactory;
|
||||
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
|
||||
// TLS v1.2 is disabled by default in API 19, use custom SSLSocketFactory to enable it
|
||||
sslSocketFactory = new TLSSocketFactory(sslContext.getSocketFactory());
|
||||
} else {
|
||||
sslSocketFactory = sslContext.getSocketFactory();
|
||||
}
|
||||
sslSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
// Automatic cookie handling, NOT PERSISTENT
|
||||
CookieJar cookieJar = new CookieJar() {
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
// Avoid duplicated cookies
|
||||
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>();
|
||||
nonDuplicatedCookiesSet.addAll(cookies);
|
||||
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>();
|
||||
nonDuplicatedCookiesList.addAll(nonDuplicatedCookiesSet);
|
||||
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>(cookies);
|
||||
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>(nonDuplicatedCookiesSet);
|
||||
|
||||
sCookieStore.put(url.host(), nonDuplicatedCookiesList);
|
||||
}
|
||||
@ -133,7 +123,7 @@ public class HttpClient {
|
||||
sOkHttpClient = clientBuilder.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Could not setup SSL system.", e);
|
||||
Timber.e(e, "Could not setup SSL system.");
|
||||
}
|
||||
}
|
||||
return sOkHttpClient;
|
||||
@ -142,7 +132,7 @@ public class HttpClient {
|
||||
private static HttpInterceptor getOkHttpInterceptor() {
|
||||
if (sOkHttpInterceptor == null) {
|
||||
sOkHttpInterceptor = new HttpInterceptor();
|
||||
addHeaderForAllRequests(HttpConstants.USER_AGENT_HEADER, OwnCloudClientManagerFactory.getUserAgent());
|
||||
addHeaderForAllRequests(HttpConstants.USER_AGENT_HEADER, SingleSessionManager.getUserAgent());
|
||||
addHeaderForAllRequests(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
|
||||
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
|
||||
}
|
||||
@ -158,7 +148,7 @@ public class HttpClient {
|
||||
public static void addHeaderForAllRequests(String headerName, String headerValue) {
|
||||
HttpInterceptor httpInterceptor = getOkHttpInterceptor();
|
||||
|
||||
if(getOkHttpInterceptor() != null) {
|
||||
if (getOkHttpInterceptor() != null) {
|
||||
httpInterceptor.addRequestInterceptor(
|
||||
new RequestHeaderInterceptor(headerName, headerValue)
|
||||
);
|
||||
@ -177,22 +167,6 @@ public class HttpClient {
|
||||
sContext = context;
|
||||
}
|
||||
|
||||
public void disableAutomaticCookiesHandling() {
|
||||
OkHttpClient.Builder clientBuilder = getOkHttpClient().newBuilder();
|
||||
clientBuilder.cookieJar(new CookieJar() {
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
});
|
||||
sOkHttpClient = clientBuilder.build();
|
||||
}
|
||||
|
||||
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
|
||||
return sCookieStore.get(httpUrl.host());
|
||||
}
|
||||
@ -200,4 +174,4 @@ public class HttpClient {
|
||||
public void clearCookies() {
|
||||
sCookieStore.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -78,14 +78,18 @@ public abstract class DavMethod extends HttpBaseMethod {
|
||||
.build();
|
||||
|
||||
} else if (mResponse != null) {
|
||||
ResponseBody responseBody = ResponseBody.create(
|
||||
mResponse.body().contentType(),
|
||||
httpException.getResponseBody()
|
||||
);
|
||||
// The check below should be included in okhttp library, method ResponseBody.create(
|
||||
// TODO check most recent versions of okhttp to see if this is already fixed and try to update if so
|
||||
if (mResponse.body().contentType() != null) {
|
||||
ResponseBody responseBody = ResponseBody.create(
|
||||
mResponse.body().contentType(),
|
||||
httpException.getResponseBody()
|
||||
);
|
||||
|
||||
mResponse = mResponse.newBuilder()
|
||||
.body(responseBody)
|
||||
.build();
|
||||
mResponse = mResponse.newBuilder()
|
||||
.body(responseBody)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
return httpException.getCode();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
@ -43,11 +43,8 @@ import java.security.cert.X509Certificate;
|
||||
*/
|
||||
public class AdvancedX509TrustManager implements X509TrustManager {
|
||||
|
||||
private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
|
||||
|
||||
private X509TrustManager mStandardTrustManager;
|
||||
private KeyStore mKnownServersKeyStore;
|
||||
|
||||
/**
|
||||
* Constructor for AdvancedX509TrustManager
|
||||
*
|
||||
@ -136,7 +133,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
|
||||
try {
|
||||
return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
|
||||
} catch (KeyStoreException e) {
|
||||
Log_OC.d(TAG, "Fail while checking certificate in the known-servers store");
|
||||
Timber.e(e, "Fail while checking certificate in the known-servers store");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,11 +24,9 @@
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import okhttp3.MediaType;
|
||||
import okio.BufferedSink;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -43,9 +41,6 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||
|
||||
private static final String TAG = ChunkFromFileRequestBody.class.getSimpleName();
|
||||
|
||||
//private final File mFile;
|
||||
private final FileChannel mChannel;
|
||||
private final long mChunkSize;
|
||||
private long mOffset;
|
||||
@ -89,17 +84,17 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
||||
while (mChannel.position() < maxCount) {
|
||||
|
||||
Log_OC.d(TAG, "Sink buffer size: " + sink.buffer().size());
|
||||
Timber.v("Sink buffer size: %s", sink.buffer().size());
|
||||
|
||||
readCount = mChannel.read(mBuffer);
|
||||
|
||||
Log_OC.d(TAG, "Read " + readCount + " bytes from file channel to " + mBuffer.toString());
|
||||
Timber.v("Read " + readCount + " bytes from file channel to " + mBuffer.toString());
|
||||
|
||||
sink.buffer().write(mBuffer.array(), 0, readCount);
|
||||
|
||||
sink.flush();
|
||||
|
||||
Log_OC.d(TAG, "Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size());
|
||||
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
|
||||
@ -113,19 +108,10 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "Chunk with size " + mChunkSize + " written in request body");
|
||||
Timber.v("Chunk with size " + mChunkSize + " written in request body");
|
||||
|
||||
} catch (Exception exception) {
|
||||
|
||||
Log.e(TAG, exception.toString());
|
||||
// // any read problem will be handled as if the file is not there
|
||||
// if (io instanceof FileNotFoundException) {
|
||||
// throw io;
|
||||
// } else {
|
||||
// FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
|
||||
// fnf.initCause(io);
|
||||
// throw fnf;
|
||||
// }
|
||||
Timber.e(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,13 +24,12 @@
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okio.BufferedSink;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
@ -45,11 +44,9 @@ import java.util.Set;
|
||||
*/
|
||||
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
|
||||
|
||||
private static final String TAG = FileRequestBody.class.getSimpleName();
|
||||
|
||||
protected File mFile;
|
||||
private MediaType mContentType;
|
||||
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||
final Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||
|
||||
public FileRequestBody(File file, MediaType contentType) {
|
||||
mFile = file;
|
||||
@ -87,11 +84,10 @@ public class FileRequestBody extends RequestBody implements ProgressiveDataTrans
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "File with name " + mFile.getName() + " and size " + mFile.length() +
|
||||
" written in request body");
|
||||
Timber.d("File with name " + mFile.getName() + " and size " + mFile.length() + " written in request body");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,7 @@ package com.owncloud.android.lib.common.network;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -42,25 +41,6 @@ import java.security.cert.CertificateException;
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
/**
|
||||
* Default timeout for waiting data from the server
|
||||
*/
|
||||
public static final int DEFAULT_DATA_TIMEOUT = 60000;
|
||||
/**
|
||||
* Default timeout for establishing a connection
|
||||
*/
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
/**
|
||||
* Standard name for protocol TLS version 1.2 in Java Secure Socket Extension (JSSE) API
|
||||
*/
|
||||
public static final String PROTOCOL_TLSv1_2 = "TLSv1.2";
|
||||
/**
|
||||
* Standard name for protocol TLS version 1.0 in JSSE API
|
||||
*/
|
||||
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
|
||||
final private static String TAG = NetworkUtils.class.getSimpleName();
|
||||
private static X509HostnameVerifier mHostnameVerifier = null;
|
||||
|
||||
private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
|
||||
|
||||
private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
|
||||
@ -88,7 +68,7 @@ public class NetworkUtils {
|
||||
//mKnownServersStore = KeyStore.getInstance("BKS");
|
||||
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
|
||||
Log_OC.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
|
||||
Timber.d("Searching known-servers store at %s", localTrustStoreFile.getAbsolutePath());
|
||||
if (localTrustStoreFile.exists()) {
|
||||
InputStream in = new FileInputStream(localTrustStoreFile);
|
||||
try {
|
||||
@ -109,22 +89,9 @@ public class NetworkUtils {
|
||||
|
||||
KeyStore knownServers = getKnownServersStore(context);
|
||||
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
|
||||
try (FileOutputStream fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE)) {
|
||||
knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCertInKnownServersStore(Certificate cert, Context context)
|
||||
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||
|
||||
KeyStore knownServers = getKnownServersStore(context);
|
||||
Log_OC.d(TAG, "Certificate - HashCode: " + cert.hashCode() + " "
|
||||
+ Boolean.toString(knownServers.isCertificateEntry(Integer.toString(cert.hashCode()))));
|
||||
return knownServers.isCertificateEntry(Integer.toString(cert.hashCode()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,145 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 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.network;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Enables the support of Server Name Indication if existing
|
||||
* in the underlying network implementation.
|
||||
* <p>
|
||||
* Build as a singleton.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class ServerNameIndicator {
|
||||
|
||||
private static final String TAG = ServerNameIndicator.class.getSimpleName();
|
||||
|
||||
private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
|
||||
|
||||
private static final String METHOD_NAME = "setHostname";
|
||||
|
||||
private final WeakReference<Class<?>> mSSLSocketClassRef;
|
||||
private final WeakReference<Method> mSetHostnameMethodRef;
|
||||
|
||||
/**
|
||||
* Private constructor, class is a singleton.
|
||||
*
|
||||
* @param sslSocketClass Underlying implementation class of {@link SSLSocket} used to connect with the server.
|
||||
* @param setHostnameMethod Name of the method to call to enable the SNI support.
|
||||
*/
|
||||
private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
|
||||
mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
|
||||
mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the {@code #setHostname(String)} method of the underlying implementation
|
||||
* of {@link SSLSocket} if exists.
|
||||
* <p>
|
||||
* Creates and initializes the single instance of the class when needed
|
||||
*
|
||||
* @param hostname The name of the server host of interest.
|
||||
* @param sslSocket Client socket to connect with the server.
|
||||
*/
|
||||
public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
|
||||
final Method setHostnameMethod = getMethod(sslSocket);
|
||||
if (setHostnameMethod != null) {
|
||||
try {
|
||||
setHostnameMethod.invoke(sslSocket, hostname);
|
||||
Log_OC.i(TAG, "SNI done, hostname: " + hostname);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
}
|
||||
} else {
|
||||
Log_OC.i(TAG, "SNI not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method to invoke trying to minimize the effective
|
||||
* application of reflection.
|
||||
*
|
||||
* @param sslSocket Instance of the SSL socket to use in connection with server.
|
||||
* @return Method to call to indicate the server name of interest to the server.
|
||||
*/
|
||||
private static Method getMethod(SSLSocket sslSocket) {
|
||||
final Class<?> sslSocketClass = sslSocket.getClass();
|
||||
final ServerNameIndicator instance = mSingleInstance.get();
|
||||
if (instance == null) {
|
||||
return initFrom(sslSocketClass);
|
||||
|
||||
} else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
|
||||
// the underlying class changed
|
||||
return initFrom(sslSocketClass);
|
||||
|
||||
} else if (instance.mSetHostnameMethodRef == null) {
|
||||
// SNI not supported
|
||||
return null;
|
||||
|
||||
} else {
|
||||
final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
|
||||
return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton initializer.
|
||||
* <p>
|
||||
* Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side.
|
||||
*
|
||||
* @param sslSocketClass Underlying class providing the implementation of {@link SSLSocket}.
|
||||
* @return Method to call to indicate the server name of interest to the server.
|
||||
*/
|
||||
private static Method initFrom(Class<?> sslSocketClass) {
|
||||
Log_OC.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName());
|
||||
Method setHostnameMethod = null;
|
||||
try {
|
||||
setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class);
|
||||
} catch (SecurityException e) {
|
||||
Log_OC.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log_OC.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported");
|
||||
}
|
||||
mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod));
|
||||
return setHostnameMethod;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2017 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.network;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Enforces, if possible, a write timeout for a socket.
|
||||
* <p>
|
||||
* Built as a singleton.
|
||||
* <p>
|
||||
* Tries to hit something like this:
|
||||
* https://android.googlesource.com/platform/external/conscrypt/+/lollipop-release/src/main/java/org/conscrypt/OpenSSLSocketImpl.java#1005
|
||||
* <p>
|
||||
* Minimizes the chances of getting stalled in PUT/POST request if the network interface is lost while
|
||||
* writing the entity into the outwards sockect.
|
||||
* <p>
|
||||
* It happens. See https://github.com/owncloud/android/issues/1684#issuecomment-295306015
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class WriteTimeoutEnforcer {
|
||||
|
||||
private static final String TAG = WriteTimeoutEnforcer.class.getSimpleName();
|
||||
|
||||
private static final AtomicReference<WriteTimeoutEnforcer> mSingleInstance = new AtomicReference<>();
|
||||
|
||||
private static final String METHOD_NAME = "setSoWriteTimeout";
|
||||
|
||||
private final WeakReference<Class<?>> mSocketClassRef;
|
||||
private final WeakReference<Method> mSetSoWriteTimeoutMethodRef;
|
||||
|
||||
/**
|
||||
* Private constructor, class is a singleton.
|
||||
*
|
||||
* @param socketClass Underlying implementation class of {@link Socket} used to connect
|
||||
* with the server.
|
||||
* @param setSoWriteTimeoutMethod Name of the method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private WriteTimeoutEnforcer(Class<?> socketClass, Method setSoWriteTimeoutMethod) {
|
||||
mSocketClassRef = new WeakReference<Class<?>>(socketClass);
|
||||
mSetSoWriteTimeoutMethodRef =
|
||||
(setSoWriteTimeoutMethod == null) ?
|
||||
null :
|
||||
new WeakReference<>(setSoWriteTimeoutMethod)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the {@code #setSoWrite(int)} method of the underlying implementation
|
||||
* of {@link Socket} if exists.
|
||||
* <p>
|
||||
* Creates and initializes the single instance of the class when needed
|
||||
*
|
||||
* @param writeTimeoutMilliseconds Write timeout to set, in milliseconds.
|
||||
* @param socket Client socket to connect with the server.
|
||||
*/
|
||||
public static void setSoWriteTimeout(int writeTimeoutMilliseconds, Socket socket) {
|
||||
final Method setSoWriteTimeoutMethod = getMethod(socket);
|
||||
if (setSoWriteTimeoutMethod != null) {
|
||||
try {
|
||||
setSoWriteTimeoutMethod.invoke(socket, writeTimeoutMilliseconds);
|
||||
Log_OC.i(
|
||||
TAG,
|
||||
"Write timeout set in socket, writeTimeoutMilliseconds: "
|
||||
+ writeTimeoutMilliseconds
|
||||
);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
}
|
||||
} else {
|
||||
Log_OC.i(TAG, "Write timeout for socket not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method to invoke trying to minimize the cost of reflection reusing objects cached
|
||||
* in static members.
|
||||
*
|
||||
* @param socket Instance of the socket to use in connection with server.
|
||||
* @return Method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private static Method getMethod(Socket socket) {
|
||||
final Class<?> socketClass = socket.getClass();
|
||||
final WriteTimeoutEnforcer instance = mSingleInstance.get();
|
||||
if (instance == null) {
|
||||
return initFrom(socketClass);
|
||||
|
||||
} else if (instance.mSocketClassRef.get() != socketClass) {
|
||||
// the underlying class changed
|
||||
return initFrom(socketClass);
|
||||
|
||||
} else if (instance.mSetSoWriteTimeoutMethodRef == null) {
|
||||
// method not supported
|
||||
return null;
|
||||
|
||||
} else {
|
||||
final Method cachedSetSoWriteTimeoutMethod = instance.mSetSoWriteTimeoutMethodRef.get();
|
||||
return (cachedSetSoWriteTimeoutMethod == null) ?
|
||||
initFrom(socketClass) :
|
||||
cachedSetSoWriteTimeoutMethod
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton initializer.
|
||||
* <p>
|
||||
* Uses reflection to extract and 'cache' the method to invoke to set a write timouet in a socket.
|
||||
*
|
||||
* @param socketClass Underlying class providing the implementation of {@link Socket}.
|
||||
* @return Method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private static Method initFrom(Class<?> socketClass) {
|
||||
Log_OC.i(TAG, "Socket implementation: " + socketClass.getCanonicalName());
|
||||
Method setSoWriteTimeoutMethod = null;
|
||||
try {
|
||||
setSoWriteTimeoutMethod = socketClass.getMethod(METHOD_NAME, int.class);
|
||||
} catch (SecurityException e) {
|
||||
Log_OC.e(TAG, "Could not access to (SocketImpl)#setSoWriteTimeout(int) method ", e);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log_OC.i(
|
||||
TAG,
|
||||
"Could not find (SocketImpl)#setSoWriteTimeout(int) method - write timeout not supported"
|
||||
);
|
||||
}
|
||||
mSingleInstance.set(new WriteTimeoutEnforcer(socketClass, setSoWriteTimeoutMethod));
|
||||
return setSoWriteTimeoutMethod;
|
||||
}
|
||||
|
||||
}
|
@ -9,13 +9,14 @@ import android.os.Handler;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudAccount;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||
import com.owncloud.android.lib.common.SingleSessionManager;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import okhttp3.OkHttpClient;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class RemoteOperation<T> implements Runnable {
|
||||
|
||||
/**
|
||||
@ -26,7 +27,6 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
* OCS API header value
|
||||
*/
|
||||
public static final String OCS_API_HEADER_VALUE = "true";
|
||||
private static final String TAG = RemoteOperation.class.getSimpleName();
|
||||
/**
|
||||
* ownCloud account in the remote ownCloud server to operate
|
||||
*/
|
||||
@ -40,22 +40,22 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
/**
|
||||
* Object to interact with the remote server
|
||||
*/
|
||||
protected OwnCloudClient mClient = null;
|
||||
private OwnCloudClient mClient = null;
|
||||
|
||||
/**
|
||||
* Object to interact with the remote server
|
||||
*/
|
||||
protected OkHttpClient mHttpClient = null;
|
||||
private OkHttpClient mHttpClient = null;
|
||||
|
||||
/**
|
||||
* Callback object to notify about the execution of the remote operation
|
||||
*/
|
||||
protected OnRemoteOperationListener mListener = null;
|
||||
private OnRemoteOperationListener mListener = null;
|
||||
|
||||
/**
|
||||
* Handler to the thread where mListener methods will be called
|
||||
*/
|
||||
protected Handler mListenerHandler = null;
|
||||
private Handler mListenerHandler = null;
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
@ -75,12 +75,10 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL Account");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
|
||||
}
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL Context");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
|
||||
}
|
||||
// mAccount and mContext in the runnerThread to create below
|
||||
mAccount = account;
|
||||
@ -106,11 +104,9 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
* the listener objects must be called.
|
||||
* @return Thread were the remote operation is executed.
|
||||
*/
|
||||
public Thread execute(OwnCloudClient client,
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
public Thread execute(OwnCloudClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
}
|
||||
mClient = client;
|
||||
if (client.getAccount() != null) {
|
||||
@ -120,8 +116,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation asynchronously " +
|
||||
"without a listener to notiy the result");
|
||||
("Trying to execute a remote operation asynchronously without a listener to notify the result");
|
||||
}
|
||||
mListener = listener;
|
||||
|
||||
@ -134,12 +129,12 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
protected void grantOwnCloudClient() throws
|
||||
private void grantOwnCloudClient() throws
|
||||
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
||||
if (mClient == null) {
|
||||
if (mAccount != null && mContext != null) {
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
mClient = SingleSessionManager.getDefaultSingleton().
|
||||
getClientFor(ocAccount, mContext);
|
||||
} else {
|
||||
throw new IllegalStateException("Trying to run a remote operation " +
|
||||
@ -177,12 +172,10 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(Account account, Context context) {
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"Account");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
|
||||
}
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"Context");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
|
||||
}
|
||||
mAccount = account;
|
||||
mContext = context.getApplicationContext();
|
||||
@ -192,7 +185,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation
|
||||
*
|
||||
* <p>
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server during the execution of
|
||||
@ -201,8 +194,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(OwnCloudClient client) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
}
|
||||
mClient = client;
|
||||
if (client.getAccount() != null) {
|
||||
@ -224,8 +216,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(OkHttpClient client, Context context) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
}
|
||||
mHttpClient = client;
|
||||
mContext = context;
|
||||
@ -236,9 +227,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
/**
|
||||
* Run operation for asynchronous or synchronous 'onExecute' method.
|
||||
* <p>
|
||||
* Considers and performs silent refresh of account credentials if possible, and if
|
||||
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
|
||||
* parameter 'true' before the execution.
|
||||
* Considers and performs silent refresh of account credentials if possible
|
||||
*
|
||||
* @return Remote operation result
|
||||
*/
|
||||
@ -251,7 +240,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
||||
result = run(mClient);
|
||||
|
||||
} catch (AccountsException | IOException e) {
|
||||
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
||||
Timber.e(e, "Error while trying to access to %s", mAccount.name);
|
||||
result = new RemoteOperationResult<>(e);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -33,9 +33,9 @@ import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import okhttp3.Headers;
|
||||
import org.json.JSONException;
|
||||
import timber.log.Timber;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
@ -60,14 +60,13 @@ public class RemoteOperationResult<T>
|
||||
*/
|
||||
private static final long serialVersionUID = 4968939884332372230L;
|
||||
|
||||
private static final String TAG = RemoteOperationResult.class.getSimpleName();
|
||||
private boolean mSuccess = false;
|
||||
private int mHttpCode = -1;
|
||||
private String mHttpPhrase = null;
|
||||
private Exception mException = null;
|
||||
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
|
||||
private String mRedirectedLocation;
|
||||
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
||||
private List<String> mAuthenticate = new ArrayList<>();
|
||||
private String mLastPermanentLocation = null;
|
||||
private T mData = null;
|
||||
|
||||
@ -189,10 +188,14 @@ public class RemoteOperationResult<T>
|
||||
try {
|
||||
if (xmlParser.parseXMLResponse(is)) {
|
||||
mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
|
||||
} else {
|
||||
parseErrorMessageAndSetCode(
|
||||
httpMethod.getResponseBodyAsString(),
|
||||
ResultCode.SPECIFIC_BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||
Timber.w("Error reading exception from server: %s", e.getMessage());
|
||||
// mCode stays as set in this(success, httpCode, headers)
|
||||
}
|
||||
}
|
||||
@ -250,7 +253,9 @@ public class RemoteOperationResult<T>
|
||||
continue;
|
||||
}
|
||||
if ("www-authenticate".equals(header.getKey().toLowerCase())) {
|
||||
mAuthenticate.add(header.getValue().get(0).toLowerCase());
|
||||
for (String value: header.getValue()) {
|
||||
mAuthenticate.add(value.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -293,11 +298,7 @@ public class RemoteOperationResult<T>
|
||||
break;
|
||||
default:
|
||||
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
||||
Log_OC.d(TAG,
|
||||
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
||||
|
||||
mHttpCode + " " + mHttpPhrase
|
||||
);
|
||||
Timber.d("RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + mHttpCode + " " + mHttpPhrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -308,21 +309,19 @@ public class RemoteOperationResult<T>
|
||||
*
|
||||
* @param bodyResponse okHttp response body
|
||||
* @param resultCode our own custom result code
|
||||
* @throws IOException
|
||||
*/
|
||||
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
|
||||
|
||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||
ErrorMessageParser xmlParser = new ErrorMessageParser();
|
||||
try {
|
||||
String errorMessage = xmlParser.parseXMLResponse(is);
|
||||
if (errorMessage != "" && errorMessage != null) {
|
||||
if (!errorMessage.equals("")) {
|
||||
mCode = resultCode;
|
||||
mHttpPhrase = errorMessage;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||
Timber.w("Error reading exception from server: %s", e.getMessage());
|
||||
// mCode stays as set in this(success, httpCode, headers)
|
||||
}
|
||||
}
|
||||
@ -376,7 +375,7 @@ public class RemoteOperationResult<T>
|
||||
previousCause = cause;
|
||||
cause = cause.getCause();
|
||||
}
|
||||
if (cause != null && cause instanceof CertificateCombinedException) {
|
||||
if (cause instanceof CertificateCombinedException) {
|
||||
result = (CertificateCombinedException) cause;
|
||||
}
|
||||
return result;
|
||||
@ -497,7 +496,7 @@ public class RemoteOperationResult<T>
|
||||
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
|
||||
}
|
||||
|
||||
public ArrayList<String> getAuthenticateHeaders() {
|
||||
public List<String> getAuthenticateHeaders() {
|
||||
return mAuthenticate;
|
||||
}
|
||||
|
||||
@ -572,6 +571,7 @@ public class RemoteOperationResult<T>
|
||||
SERVICE_UNAVAILABLE,
|
||||
SPECIFIC_SERVICE_UNAVAILABLE,
|
||||
SPECIFIC_UNSUPPORTED_MEDIA_TYPE,
|
||||
SPECIFIC_METHOD_NOT_ALLOWED
|
||||
SPECIFIC_METHOD_NOT_ALLOWED,
|
||||
SPECIFIC_BAD_REQUEST
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
package com.owncloud.android.lib.common.utils;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Log_OC {
|
||||
|
||||
private static String mOwncloudDataFolderLog;
|
||||
|
||||
public static void setLogDataFolder(String logFolder) {
|
||||
mOwncloudDataFolderLog = logFolder;
|
||||
}
|
||||
|
||||
public static void i(String message) {
|
||||
Timber.i(message);
|
||||
}
|
||||
|
||||
public static void d(String message) {
|
||||
Timber.d(message);
|
||||
}
|
||||
|
||||
public static void d(String message, Exception e) {
|
||||
Timber.d(e, message);
|
||||
}
|
||||
|
||||
public static void e(String message) {
|
||||
Timber.e(message);
|
||||
}
|
||||
|
||||
public static void e(String message, Throwable e) {
|
||||
Timber.e(e, message);
|
||||
}
|
||||
|
||||
public static void v(String message) {
|
||||
Timber.v(message);
|
||||
}
|
||||
|
||||
public static void w(String message) {
|
||||
Timber.w(message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void i(String tag, String message) {
|
||||
Timber.i(message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void d(String TAG, String message) {
|
||||
Timber.d(message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void d(String TAG, String message, Exception e) {
|
||||
Timber.d(e, message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void e(String TAG, String message) {
|
||||
Timber.e(message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void e(String TAG, String message, Throwable e) {
|
||||
Timber.e(e, message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void v(String TAG, String message) {
|
||||
Timber.v(message);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void w(String TAG, String message) {
|
||||
Timber.w(message);
|
||||
}
|
||||
|
||||
public static void startLogging(String storagePath) {
|
||||
LoggingHelper.INSTANCE.startLogging(
|
||||
new File(storagePath+ File.separator + mOwncloudDataFolderLog), mOwncloudDataFolderLog);
|
||||
}
|
||||
|
||||
public static void stopLogging() {
|
||||
LoggingHelper.INSTANCE.stopLogging();
|
||||
}
|
||||
|
||||
}
|
@ -13,7 +13,7 @@ object LoggingHelper {
|
||||
}
|
||||
if (!directory.exists())
|
||||
directory.mkdirs()
|
||||
Timber.plant(FileLoggingTree(directory, filename = storagePath, delegator = Log_OC::class.java))
|
||||
Timber.plant(FileLoggingTree(directory, filename = storagePath))
|
||||
}
|
||||
|
||||
fun stopLogging() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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,
|
||||
|
@ -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<Boolean>() {
|
||||
/**
|
||||
* 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<Boolean> {
|
||||
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<Boolean>(ResultCode.OK).apply { data = true }
|
||||
else RemoteOperationResult<Boolean>(propFindMethod).apply { data = false }
|
||||
|
||||
} catch (e: Exception) {
|
||||
val result = RemoteOperationResult<Boolean>(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
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,8 +24,6 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod;
|
||||
@ -33,7 +31,7 @@ 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 com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -41,16 +39,15 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||
* in the same account.
|
||||
* <p>
|
||||
*
|
||||
* Allows renaming the moving file/folder at the same time.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
* @author David González V.
|
||||
*/
|
||||
public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
||||
|
||||
private static final String TAG = CopyRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int COPY_READ_TIMEOUT = 600000;
|
||||
private static final int COPY_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
@ -81,14 +78,6 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult<String> run(OwnCloudClient client) {
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
/// check parameters
|
||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||
// nothing to do!
|
||||
@ -100,7 +89,7 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
||||
}
|
||||
|
||||
/// perform remote operation
|
||||
RemoteOperationResult<String> result;
|
||||
RemoteOperationResult result;
|
||||
try {
|
||||
CopyMethod copyMethod =
|
||||
new CopyMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||
@ -128,13 +117,11 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
Log.i(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
Timber.i("Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
Timber.e(e, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* Copyright (C) 2019 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
|
||||
@ -33,8 +33,7 @@ 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 com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -47,8 +46,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = CreateRemoteFolderOperation.class.getSimpleName();
|
||||
|
||||
private static final int READ_TIMEOUT = 30000;
|
||||
private static final int CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
@ -75,24 +72,14 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars);
|
||||
if (noInvalidChars) {
|
||||
result = createFolder(client);
|
||||
if (!result.isSuccess() && mCreateFullPath &&
|
||||
RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) {
|
||||
result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
|
||||
if (result.isSuccess()) {
|
||||
result = createFolder(client); // second (and last) try
|
||||
}
|
||||
RemoteOperationResult result = createFolder(client);
|
||||
if (!result.isSuccess() && mCreateFullPath &&
|
||||
RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) {
|
||||
result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
|
||||
if (result.isSuccess()) {
|
||||
result = createFolder(client); // second (and last) try
|
||||
}
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -108,12 +95,12 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||
result = (status == HttpConstants.HTTP_CREATED)
|
||||
? new RemoteOperationResult<>(ResultCode.OK)
|
||||
: new RemoteOperationResult<>(mkcol);
|
||||
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||
Timber.d("Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||
Timber.e(e, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -123,4 +110,4 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath, mCreateFullPath);
|
||||
return operation.execute(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
@ -53,7 +53,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName();
|
||||
private static final int FORBIDDEN_ERROR = 403;
|
||||
private static final int SERVICE_UNAVAILABLE_ERROR = 503;
|
||||
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
@ -81,13 +80,11 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
try {
|
||||
tmpFile.getParentFile().mkdirs();
|
||||
result = downloadFile(client, tmpFile);
|
||||
Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
||||
result.getLogMessage());
|
||||
Timber.i("Download of " + mRemotePath + " to " + getTmpPath() + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
||||
result.getLogMessage(), e);
|
||||
Timber.e(e, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -149,7 +146,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
final Date d = WebdavUtils.parseResponseDate(modificationTime);
|
||||
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
||||
} else {
|
||||
Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath);
|
||||
Timber.e("Could not read modification time from response downloading %s", mRemotePath);
|
||||
}
|
||||
|
||||
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
||||
@ -158,7 +155,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
mEtag = mEtag.replace("\"", "");
|
||||
|
||||
if (mEtag.length() == 0) {
|
||||
Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath);
|
||||
Timber.e("Could not read eTag from response downloading %s", mRemotePath);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -1,153 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 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.utils.Log_OC;
|
||||
|
||||
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 static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
Log_OC.d(TAG, "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);
|
||||
Log_OC.e(TAG, "Existence check for " + client.getUserFilesWebDavUri() +
|
||||
WebdavUtils.encodePath(mPath) + " targeting for " +
|
||||
(mSuccessIfAbsent ? " absence " : " existence ") + ": " +
|
||||
result.getLogMessage(), result.getException());
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,17 +24,15 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
public static final String PATH_SEPARATOR = "/";
|
||||
public static final String FINAL_CHUNKS_FILE = ".file";
|
||||
private static final String TAG = FileUtils.class.getSimpleName();
|
||||
|
||||
public static String getParentPath(String remotePath) {
|
||||
static String getParentPath(String remotePath) {
|
||||
String parentPath = new File(remotePath).getParent();
|
||||
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
|
||||
return parentPath;
|
||||
@ -45,40 +43,13 @@ public class FileUtils {
|
||||
* : , " , | , ? , *
|
||||
*
|
||||
* @param fileName
|
||||
* @param versionSupportsForbiddenChars
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
|
||||
public static boolean isValidName(String fileName) {
|
||||
boolean result = true;
|
||||
|
||||
Log_OC.d(TAG, "fileName =======" + fileName);
|
||||
if ((versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
|
||||
(!versionSupportsForbiddenChars && (fileName.contains(PATH_SEPARATOR) ||
|
||||
fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
|
||||
fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
|
||||
fileName.contains("?") || fileName.contains("*")))) {
|
||||
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | ,
|
||||
* ? , *
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidPath(String path, boolean versionSupportsForbidenChars) {
|
||||
boolean result = true;
|
||||
|
||||
Log_OC.d(TAG, "path ....... " + path);
|
||||
if (!versionSupportsForbidenChars &&
|
||||
(path.contains("\\") || path.contains("<") || path.contains(">") ||
|
||||
path.contains(":") || path.contains("\"") || path.contains("|") ||
|
||||
path.contains("?") || path.contains("*"))) {
|
||||
|
||||
Timber.d("fileName =======%s", fileName);
|
||||
if (fileName.contains(PATH_SEPARATOR)) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -25,7 +25,6 @@
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
@ -34,7 +33,7 @@ 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 com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -50,8 +49,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class MoveRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = MoveRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int MOVE_READ_TIMEOUT = 600000;
|
||||
private static final int MOVE_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
@ -87,16 +84,6 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
/// check parameters
|
||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||
// nothing to do!
|
||||
return new RemoteOperationResult<>(ResultCode.OK);
|
||||
@ -143,13 +130,11 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
Log.i(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
Timber.i("Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
Timber.e(e, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -158,4 +143,4 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
||||
protected boolean isSuccess(int status) {
|
||||
return status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||
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.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -49,7 +49,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
||||
|
||||
public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
|
||||
|
||||
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
|
||||
private static final int SYNC_READ_TIMEOUT = 40000;
|
||||
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
@ -100,9 +99,7 @@ public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
e.printStackTrace();
|
||||
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
|
||||
result.getException());
|
||||
Timber.e(e, "Synchronizing file %s", mRemotePath);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -34,7 +34,7 @@ import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||
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.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
@ -51,8 +51,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
||||
|
||||
public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteFile>> {
|
||||
|
||||
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
|
||||
|
||||
private String mRemotePath;
|
||||
|
||||
/**
|
||||
@ -108,14 +106,15 @@ public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteF
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
} finally {
|
||||
if (result.isSuccess()) {
|
||||
Log_OC.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
if (result == null) {
|
||||
Timber.e("Synchronized " + mRemotePath + ": result is null");
|
||||
} else if (result.isSuccess()) {
|
||||
Timber.i("Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
} else {
|
||||
if (result.isException()) {
|
||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(),
|
||||
result.getException());
|
||||
Timber.e(result.getException(), "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
} else {
|
||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
Timber.e("Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,7 +24,6 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@ -41,14 +40,11 @@ import at.bitfire.dav4android.property.owncloud.OCId;
|
||||
import at.bitfire.dav4android.property.owncloud.OCPermissions;
|
||||
import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
|
||||
import at.bitfire.dav4android.property.owncloud.OCSize;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0;
|
||||
|
||||
/**
|
||||
* Contains the data of a Remote File from a WebDavEntry
|
||||
*
|
||||
@ -115,7 +111,7 @@ public class RemoteFile implements Parcelable, Serializable {
|
||||
}
|
||||
|
||||
public RemoteFile(final Response davResource, String userId) {
|
||||
this(getRemotePathFromUrl(davResource.getHref(), userId));
|
||||
this(RemoteFileUtil.Companion.getRemotePathFromUrl(davResource.getHref(), userId));
|
||||
final List<Property> properties = davResource.getProperties();
|
||||
|
||||
for (Property property : properties) {
|
||||
@ -167,21 +163,6 @@ public class RemoteFile implements Parcelable, Serializable {
|
||||
readFromParcel(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a relative path from a remote file url
|
||||
* <p>
|
||||
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
|
||||
*
|
||||
* @param url remote file url
|
||||
* @param userId file owner
|
||||
* @return remote relative path of the file
|
||||
*/
|
||||
private static String getRemotePathFromUrl(HttpUrl url, String userId) {
|
||||
final String davFilesPath = WEBDAV_FILES_PATH_4_0 + userId;
|
||||
final String absoluteDavPath = Uri.decode(url.encodedPath());
|
||||
final String pathToOc = absoluteDavPath.split(davFilesPath)[0];
|
||||
return absoluteDavPath.replace(pathToOc + davFilesPath, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Getters and Setters
|
||||
|
@ -1,7 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
* 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
|
||||
@ -23,44 +21,29 @@
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.files
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
import android.net.Uri
|
||||
import com.owncloud.android.lib.common.OwnCloudClient
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
public class OAuth2ClientConfiguration {
|
||||
|
||||
private String mClientId;
|
||||
|
||||
private String mClientSecret;
|
||||
|
||||
private String mRedirectUri;
|
||||
|
||||
public OAuth2ClientConfiguration(String clientId, String clientSecret, String redirectUri) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return mClientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return mClientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
return mRedirectUri;
|
||||
}
|
||||
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
this.mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
class RemoteFileUtil {
|
||||
companion object {
|
||||
/**
|
||||
* Retrieves a relative path from a remote file url
|
||||
*
|
||||
*
|
||||
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
|
||||
*
|
||||
* @param url remote file url
|
||||
* @param userId file owner
|
||||
* @return remote relative path of the file
|
||||
*/
|
||||
fun getRemotePathFromUrl(url: HttpUrl, userId: String): String? {
|
||||
val davFilesPath = OwnCloudClient.WEBDAV_FILES_PATH_4_0 + userId
|
||||
val absoluteDavPath = Uri.decode(url.encodedPath())
|
||||
val pathToOc = absoluteDavPath.split(davFilesPath)[0]
|
||||
return absoluteDavPath.replace(pathToOc + davFilesPath, "")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -32,7 +32,7 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod;
|
||||
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.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@ -46,7 +46,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class RemoveRemoteFileOperation extends RemoteOperation {
|
||||
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
|
||||
private String mRemotePath;
|
||||
|
||||
protected boolean removeChunksFolder = false;
|
||||
@ -81,11 +80,11 @@ public class RemoveRemoteFileOperation extends RemoteOperation {
|
||||
new RemoteOperationResult<>(OK) :
|
||||
new RemoteOperationResult<>(deleteMethod);
|
||||
|
||||
Log_OC.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||
Timber.i("Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||
Timber.e(e, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* Copyright (C) 2019 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
|
||||
@ -31,8 +31,7 @@ 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 com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
@ -46,8 +45,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class RenameRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = RenameRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int RENAME_READ_TIMEOUT = 600000;
|
||||
private static final int RENAME_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
@ -86,15 +83,6 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
final OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
final boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
if (!FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
try {
|
||||
if (mNewName.equals(mOldName)) {
|
||||
return new RemoteOperationResult<>(ResultCode.OK);
|
||||
@ -117,16 +105,14 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
||||
? new RemoteOperationResult<>(ResultCode.OK)
|
||||
: new RemoteOperationResult<>(move);
|
||||
|
||||
Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
|
||||
result.getLogMessage()
|
||||
);
|
||||
Timber.i("Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " + result.getLogMessage());
|
||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
|
||||
((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ": " +
|
||||
result.getLogMessage(), e);
|
||||
Timber.e(e,
|
||||
"Rename " + mOldRemotePath + " to " + ((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ":" +
|
||||
" " + result.getLogMessage());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -137,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();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -33,8 +33,8 @@ import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import okhttp3.MediaType;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
@ -54,7 +54,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
||||
|
||||
public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
||||
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
protected String mLocalPath;
|
||||
protected String mRemotePath;
|
||||
@ -62,7 +61,7 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
protected String mFileLastModifTimestamp;
|
||||
protected PutMethod mPutMethod = null;
|
||||
protected String mRequiredEtag = null;
|
||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||
|
||||
protected FileRequestBody mFileRequestBody = null;
|
||||
|
||||
@ -96,27 +95,25 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
} else {
|
||||
// perform the upload
|
||||
result = uploadFile(client);
|
||||
Log_OC.i(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
Timber.i("Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
if (mPutMethod != null && mPutMethod.isAborted()) {
|
||||
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage(), new OperationCancelledException());
|
||||
Timber.e(result.getException(),
|
||||
"Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
Timber.e(e, "Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected RemoteOperationResult<? extends Object> uploadFile(OwnCloudClient client) throws Exception {
|
||||
protected RemoteOperationResult<?> uploadFile(OwnCloudClient client) throws Exception {
|
||||
|
||||
File fileToUpload = new File(mLocalPath);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -29,10 +29,10 @@ import com.owncloud.android.lib.common.http.methods.webdav.PutMethod;
|
||||
import com.owncloud.android.lib.common.network.ChunkFromFileRequestBody;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||
import okhttp3.MediaType;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
@ -53,7 +53,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
||||
|
||||
public static final long CHUNK_SIZE = 1024000;
|
||||
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
||||
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private String mTransferId;
|
||||
|
||||
@ -113,7 +112,7 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
||||
|
||||
status = client.executeHttpMethod(mPutMethod);
|
||||
|
||||
Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath +
|
||||
Timber.d("Upload of " + mLocalPath + " to " + mRemotePath +
|
||||
", chunk index " + chunkIndex + ", count " + chunkCount +
|
||||
", HTTP result status " + status);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -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<Boolean>
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Boolean> =
|
||||
CheckPathExistenceRemoteOperation(
|
||||
remotePath = path,
|
||||
isUserLogged = isUserLogged
|
||||
).execute(client)
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author Abel García de Prada
|
||||
* 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.response
|
||||
|
||||
import com.owncloud.android.lib.resources.status.RemoteCapability
|
||||
import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBooleanType
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CapabilityResponse(
|
||||
@Json(name = "version")
|
||||
val serverVersion: ServerVersion?,
|
||||
val capabilities: Capabilities?
|
||||
) {
|
||||
fun toRemoteCapability(): RemoteCapability = RemoteCapability(
|
||||
versionMayor = serverVersion?.major ?: 0,
|
||||
versionMinor = serverVersion?.minor ?: 0,
|
||||
versionMicro = serverVersion?.micro ?: 0,
|
||||
versionString = serverVersion?.string ?: "",
|
||||
versionEdition = serverVersion?.edition ?: "",
|
||||
corePollinterval = capabilities?.coreCapabilities?.pollinterval ?: 0,
|
||||
chunkingVersion = capabilities?.davCapabilities?.chunking ?: "",
|
||||
filesSharingApiEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingApiEnabled),
|
||||
filesSharingResharing = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingReSharing),
|
||||
filesSharingPublicEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.enabled),
|
||||
filesSharingPublicUpload = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUpload),
|
||||
filesSharingPublicSupportsUploadOnly = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUploadOnly),
|
||||
filesSharingPublicMultiple = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicMultiple),
|
||||
filesSharingPublicPasswordEnforced = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforced),
|
||||
filesSharingPublicPasswordEnforcedReadOnly = CapabilityBooleanType.fromBooleanValue(
|
||||
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforcedFor?.enforcedReadOnly
|
||||
),
|
||||
filesSharingPublicPasswordEnforcedReadWrite = CapabilityBooleanType.fromBooleanValue(
|
||||
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforcedFor?.enforcedReadWrite
|
||||
),
|
||||
filesSharingPublicPasswordEnforcedUploadOnly = CapabilityBooleanType.fromBooleanValue(
|
||||
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforcedFor?.enforcedUploadOnly
|
||||
),
|
||||
filesSharingPublicExpireDateEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.enabled),
|
||||
filesSharingPublicExpireDateDays = capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.days
|
||||
?: 0,
|
||||
filesSharingPublicExpireDateEnforced = CapabilityBooleanType.fromBooleanValue(
|
||||
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.enforced
|
||||
),
|
||||
filesBigFileChunking = CapabilityBooleanType.fromBooleanValue(capabilities?.fileCapabilities?.bigfilechunking),
|
||||
filesUndelete = CapabilityBooleanType.fromBooleanValue(capabilities?.fileCapabilities?.undelete),
|
||||
filesVersioning = CapabilityBooleanType.fromBooleanValue(capabilities?.fileCapabilities?.versioning),
|
||||
filesSharingFederationIncoming = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.incoming),
|
||||
filesSharingFederationOutgoing = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.outgoing)
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Capabilities(
|
||||
@Json(name = "core")
|
||||
val coreCapabilities: CoreCapabilities?,
|
||||
@Json(name = "files_sharing")
|
||||
val fileSharingCapabilities: FileSharingCapabilities?,
|
||||
@Json(name = "files")
|
||||
val fileCapabilities: FileCapabilities?,
|
||||
@Json(name = "dav")
|
||||
val davCapabilities: DavCapabilities?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CoreCapabilities(
|
||||
val pollinterval: Int?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingCapabilities(
|
||||
@Json(name = "api_enabled")
|
||||
val fileSharingApiEnabled: Boolean?,
|
||||
@Json(name = "public")
|
||||
val fileSharingPublic: FileSharingPublic?,
|
||||
@Json(name = "resharing")
|
||||
val fileSharingReSharing: Boolean?,
|
||||
@Json(name = "federation")
|
||||
val fileSharingFederation: FileSharingFederation?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingPublic(
|
||||
val enabled: Boolean?,
|
||||
@Json(name = "upload")
|
||||
val fileSharingPublicUpload: Boolean?,
|
||||
@Json(name = "supports_upload_only")
|
||||
val fileSharingPublicUploadOnly: Boolean?,
|
||||
@Json(name = "multiple")
|
||||
val fileSharingPublicMultiple: Boolean?,
|
||||
@Json(name = "password")
|
||||
val fileSharingPublicPassword: FileSharingPublicPassword?,
|
||||
@Json(name = "expire_date")
|
||||
val fileSharingPublicExpireDate: FileSharingPublicExpireDate?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingPublicPassword(
|
||||
val enforced: Boolean?,
|
||||
@Json(name = "enforced_for")
|
||||
val enforcedFor: FileSharingPublicPasswordEnforced?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingPublicPasswordEnforced(
|
||||
@Json(name = "read_only")
|
||||
val enforcedReadOnly: Boolean?,
|
||||
@Json(name = "read_write")
|
||||
val enforcedReadWrite: Boolean?,
|
||||
@Json(name = "upload_only")
|
||||
val enforcedUploadOnly: Boolean?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingPublicExpireDate(
|
||||
val enabled: Boolean?,
|
||||
val days: Int?,
|
||||
val enforced: Boolean?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileSharingFederation(
|
||||
val incoming: Boolean?,
|
||||
val outgoing: Boolean?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FileCapabilities(
|
||||
val bigfilechunking: Boolean?,
|
||||
val undelete: Boolean?,
|
||||
val versioning: Boolean?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DavCapabilities(
|
||||
val chunking: String?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ServerVersion(
|
||||
var major: Int?,
|
||||
var minor: Int?,
|
||||
var micro: Int?,
|
||||
var string: String?,
|
||||
var edition: String?
|
||||
)
|
@ -1,5 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
*
|
||||
* 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
|
||||
@ -19,34 +20,27 @@
|
||||
* 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.response
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
// 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<T>(
|
||||
val ocs: OCSResponse<T>
|
||||
)
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class OCSResponse<T>(
|
||||
val meta: MetaData,
|
||||
val data: T
|
||||
)
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Manager to create and reuse OwnCloudClient instances to access remote OC servers.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
|
||||
public interface OwnCloudClientManager {
|
||||
|
||||
OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException,
|
||||
OperationCanceledException, AuthenticatorException, IOException;
|
||||
|
||||
OwnCloudClient removeClientFor(OwnCloudAccount account);
|
||||
|
||||
void saveAllClients(Context context, String accountType) throws AccountNotFoundException, AuthenticatorException, IOException,
|
||||
OperationCanceledException;
|
||||
}
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MetaData(
|
||||
val status: String,
|
||||
val statuscode: Int,
|
||||
val message: String?
|
||||
)
|
@ -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.response
|
||||
|
||||
import com.owncloud.android.lib.resources.users.RemoteUserInfo
|
||||
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 toRemoteUserInfo() = RemoteUserInfo(
|
||||
id = id,
|
||||
displayName = displayName,
|
||||
email = email
|
||||
)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH
|
||||
* 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
|
||||
@ -32,9 +32,9 @@ import com.owncloud.android.lib.common.http.HttpConstants
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.lib.resources.shares.RemoteShare.Companion.INIT_EXPIRATION_DATE_IN_MILLIS
|
||||
import okhttp3.FormBody
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
@ -150,7 +150,7 @@ class CreateRemoteShareOperation(
|
||||
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Exception while Creating New Share", e)
|
||||
Timber.e(e, "Exception while Creating New Share")
|
||||
}
|
||||
|
||||
return result
|
||||
@ -159,8 +159,6 @@ class CreateRemoteShareOperation(
|
||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
private val TAG = CreateRemoteShareOperation::class.java.simpleName
|
||||
|
||||
private const val PARAM_NAME = "name"
|
||||
private const val PARAM_PASSWORD = "password"
|
||||
private const val PARAM_EXPIRATION_DATE = "expireDate"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -33,7 +33,7 @@ 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.utils.Log_OC;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@ -46,8 +46,6 @@ import java.net.URL;
|
||||
|
||||
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||
|
||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
||||
|
||||
private long mRemoteId;
|
||||
|
||||
public GetRemoteShareOperation(long remoteId) {
|
||||
@ -85,7 +83,7 @@ public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult>
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
||||
Timber.e(e, "Exception while getting remote shares");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -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.common.utils.Log_OC
|
||||
import org.json.JSONObject
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import java.util.ArrayList
|
||||
|
||||
@ -95,13 +95,13 @@ class GetRemoteShareesOperation
|
||||
|
||||
val getMethod = GetMethod(URL(uriBuilder.build().toString()))
|
||||
|
||||
getMethod.addRequestHeader(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE)
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||
|
||||
val status = client.executeHttpMethod(getMethod)
|
||||
val response = getMethod.responseBodyAsString
|
||||
|
||||
if (isSuccess(status)) {
|
||||
Log_OC.d(TAG, "Successful response: " + response!!)
|
||||
Timber.d("Successful response: $response")
|
||||
|
||||
// Parse the response
|
||||
val respJSON = JSONObject(response)
|
||||
@ -128,65 +128,61 @@ class GetRemoteShareesOperation
|
||||
for (j in 0 until jsonResults[i].length()) {
|
||||
val jsonResult = jsonResults[i].getJSONObject(j)
|
||||
data.add(jsonResult)
|
||||
Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL))
|
||||
Timber.d("*** Added item: ${jsonResult.getString(PROPERTY_LABEL)}")
|
||||
}
|
||||
}
|
||||
|
||||
result = RemoteOperationResult(OK)
|
||||
result.data = data
|
||||
|
||||
Log_OC.d(TAG, "*** Get Users or groups completed ")
|
||||
Timber.d("*** Get Users or groups completed ")
|
||||
|
||||
} else {
|
||||
result = RemoteOperationResult(getMethod)
|
||||
Log_OC.e(TAG, "Failed response while getting users/groups from the server ")
|
||||
Timber.e("Failed response while getting users/groups from the server ")
|
||||
if (response != null) {
|
||||
Log_OC.e(TAG, "*** status code: $status; response message: $response")
|
||||
Timber.e("*** status code: $status; response message: $response")
|
||||
} else {
|
||||
Log_OC.e(TAG, "*** status code: $status")
|
||||
Timber.e("*** status code: $status")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Exception while getting users/groups", e)
|
||||
Timber.e(e, "Exception while getting users/groups")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun isSuccess(status: Int): Boolean {
|
||||
return status == HttpConstants.HTTP_OK
|
||||
}
|
||||
private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = GetRemoteShareesOperation::class.java.simpleName
|
||||
|
||||
// OCS Routes
|
||||
private val OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees" // from OC 8.2
|
||||
private const val OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees" // from OC 8.2
|
||||
|
||||
// Arguments - names
|
||||
private val PARAM_FORMAT = "format"
|
||||
private val PARAM_ITEM_TYPE = "itemType"
|
||||
private val PARAM_SEARCH = "search"
|
||||
private val PARAM_PAGE = "page" // default = 1
|
||||
private val PARAM_PER_PAGE = "perPage" // default = 200
|
||||
private const val PARAM_FORMAT = "format"
|
||||
private const val PARAM_ITEM_TYPE = "itemType"
|
||||
private const val PARAM_SEARCH = "search"
|
||||
private const val PARAM_PAGE = "page" // default = 1
|
||||
private const val PARAM_PER_PAGE = "perPage" // default = 200
|
||||
|
||||
// Arguments - constant values
|
||||
private val VALUE_FORMAT = "json"
|
||||
private val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups
|
||||
private const val VALUE_FORMAT = "json"
|
||||
private const val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups
|
||||
|
||||
// JSON Node names
|
||||
private val NODE_OCS = "ocs"
|
||||
private val NODE_DATA = "data"
|
||||
private val NODE_EXACT = "exact"
|
||||
private val NODE_USERS = "users"
|
||||
private val NODE_GROUPS = "groups"
|
||||
private val NODE_REMOTES = "remotes"
|
||||
val NODE_VALUE = "value"
|
||||
val PROPERTY_LABEL = "label"
|
||||
val PROPERTY_SHARE_TYPE = "shareType"
|
||||
val PROPERTY_SHARE_WITH = "shareWith"
|
||||
val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo"
|
||||
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"
|
||||
const val PROPERTY_SHARE_WITH = "shareWith"
|
||||
const val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -32,7 +32,7 @@ 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.utils.Log_OC
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
@ -89,14 +89,14 @@ class GetRemoteSharesForFileOperation(
|
||||
result = parser.parse(getMethod.responseBodyAsString)
|
||||
|
||||
if (result.isSuccess) {
|
||||
Log_OC.d(TAG, "Got " + result.data.shares.size + " shares")
|
||||
Timber.d("Got " + result.data.shares.size + " shares")
|
||||
}
|
||||
} else {
|
||||
result = RemoteOperationResult(getMethod)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Exception while getting shares", e)
|
||||
Timber.e(e, "Exception while getting shares")
|
||||
}
|
||||
|
||||
return result
|
||||
@ -105,11 +105,8 @@ class GetRemoteSharesForFileOperation(
|
||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = GetRemoteSharesForFileOperation::class.java.simpleName
|
||||
|
||||
private const val PARAM_PATH = "path"
|
||||
private const val PARAM_RESHARES = "reshares"
|
||||
private const val PARAM_SUBFILES = "subfiles"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -42,8 +42,8 @@ data class RemoteShare(
|
||||
var sharedWithAdditionalInfo: String = "",
|
||||
var name: String = "",
|
||||
var shareLink: String = "",
|
||||
var fileSource: Long = 0,
|
||||
var itemSource: Long = 0,
|
||||
var fileSource: String = "0",
|
||||
var itemSource: String = "0",
|
||||
var shareType: ShareType? = ShareType.UNKNOWN,
|
||||
var permissions: Int = DEFAULT_PERMISSION,
|
||||
var sharedDate: Long = INIT_SHARED_DATE,
|
||||
@ -66,16 +66,14 @@ data class RemoteShare(
|
||||
const val MAXIMUM_PERMISSIONS_FOR_FOLDER = MAXIMUM_PERMISSIONS_FOR_FILE +
|
||||
CREATE_PERMISSION_FLAG +
|
||||
DELETE_PERMISSION_FLAG
|
||||
const val FEDERATED_PERMISSIONS_FOR_FILE_UP_TO_OC9 = READ_PERMISSION_FLAG + UPDATE_PERMISSION_FLAG
|
||||
const val FEDERATED_PERMISSIONS_FOR_FILE_AFTER_OC9 = READ_PERMISSION_FLAG +
|
||||
const val FEDERATED_PERMISSIONS_FOR_FILE = READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG +
|
||||
SHARE_PERMISSION_FLAG
|
||||
const val FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 = READ_PERMISSION_FLAG +
|
||||
const val FEDERATED_PERMISSIONS_FOR_FOLDER = READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG +
|
||||
CREATE_PERMISSION_FLAG +
|
||||
DELETE_PERMISSION_FLAG
|
||||
const val FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9 =
|
||||
FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 + SHARE_PERMISSION_FLAG
|
||||
DELETE_PERMISSION_FLAG +
|
||||
SHARE_PERMISSION_FLAG
|
||||
|
||||
const val INIT_EXPIRATION_DATE_IN_MILLIS: Long = 0
|
||||
const val INIT_SHARED_DATE: Long = 0
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -32,7 +32,7 @@ import com.owncloud.android.lib.common.http.HttpConstants
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
@ -75,7 +75,7 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
|
||||
)
|
||||
result = parser.parse(deleteMethod.responseBodyAsString)
|
||||
|
||||
Log_OC.d(TAG, "Unshare " + remoteShareId + ": " + result.logMessage)
|
||||
Timber.d("Unshare " + remoteShareId + ": " + result.logMessage)
|
||||
|
||||
} else {
|
||||
result = RemoteOperationResult(deleteMethod)
|
||||
@ -83,16 +83,11 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
|
||||
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Unshare Link Exception " + result.logMessage, e)
|
||||
Timber.e(e, "Unshare Link Exception " + result.logMessage)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = RemoveRemoteShareOperation::class.java.simpleName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -29,9 +29,9 @@ package com.owncloud.android.lib.resources.shares
|
||||
|
||||
import android.net.Uri
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
import timber.log.Timber
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.IOException
|
||||
import java.util.ArrayList
|
||||
@ -53,7 +53,7 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
||||
// Parse xml response and obtain the list of shares
|
||||
val byteArrayServerResponse = ByteArrayInputStream(serverResponse.toByteArray())
|
||||
if (shareXmlParser == null) {
|
||||
Log_OC.w(TAG, "No ShareXmlParser provided, creating new instance ")
|
||||
Timber.w("No ShareXmlParser provided, creating new instance")
|
||||
shareXmlParser = ShareXMLParser()
|
||||
}
|
||||
val shares = shareXmlParser?.parseXMLResponse(byteArrayServerResponse)
|
||||
@ -72,10 +72,10 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
||||
}
|
||||
|
||||
if (serverBaseUri != null) {
|
||||
val sharingLinkPath = ShareUtils.getSharingLinkPath(ownCloudVersion)
|
||||
val sharingLinkPath = ShareUtils.SHARING_LINK_PATH
|
||||
share.shareLink = serverBaseUri.toString() + sharingLinkPath + share.token
|
||||
} else {
|
||||
Log_OC.e(TAG, "Couldn't build link for public share :(")
|
||||
Timber.e("Couldn't build link for public share :(")
|
||||
}
|
||||
|
||||
share
|
||||
@ -87,7 +87,7 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
||||
|
||||
} else {
|
||||
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
||||
Log_OC.e(TAG, "Successful status with no share in the response")
|
||||
Timber.e("Successful status with no share in the response")
|
||||
}
|
||||
}
|
||||
shareXmlParser?.isWrongParameter!! -> {
|
||||
@ -107,18 +107,14 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
||||
}
|
||||
}
|
||||
} catch (e: XmlPullParserException) {
|
||||
Log_OC.e(TAG, "Error parsing response from server ", e)
|
||||
Timber.e(e, "Error parsing response from server")
|
||||
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
||||
|
||||
} catch (e: IOException) {
|
||||
Log_OC.e(TAG, "Error reading response from server ", e)
|
||||
Timber.e(e, "Error reading response from server")
|
||||
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = ShareToRemoteOperationResultParser::class.java.simpleName
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -24,8 +24,6 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.shares;
|
||||
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
/**
|
||||
* Contains Constants for Share Operation
|
||||
*
|
||||
@ -39,14 +37,5 @@ public class ShareUtils {
|
||||
public static final String SHARING_API_PATH = "ocs/v2.php/apps/files_sharing/api/v1/shares";
|
||||
|
||||
// String to build the link with the token of a share:
|
||||
public static final String SHARING_LINK_PATH_BEFORE_VERSION_8 = "/public.php?service=files&t=";
|
||||
public static final String SHARING_LINK_PATH_AFTER_VERSION_8 = "/index.php/s/";
|
||||
|
||||
public static String getSharingLinkPath(OwnCloudVersion version) {
|
||||
if (version != null && version.isAfter8Version()) {
|
||||
return SHARING_LINK_PATH_AFTER_VERSION_8;
|
||||
} else {
|
||||
return SHARING_LINK_PATH_BEFORE_VERSION_8;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final String SHARING_LINK_PATH = "/index.php/s/";
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -110,12 +110,16 @@ class ShareXMLParser {
|
||||
}
|
||||
val name = parser.name
|
||||
// read NODE_META and NODE_DATA
|
||||
if (name.equals(NODE_META, ignoreCase = true)) {
|
||||
readMeta(parser)
|
||||
} else if (name.equals(NODE_DATA, ignoreCase = true)) {
|
||||
shares = readData(parser)
|
||||
} else {
|
||||
skip(parser)
|
||||
when {
|
||||
name.equals(NODE_META, ignoreCase = true) -> {
|
||||
readMeta(parser)
|
||||
}
|
||||
name.equals(NODE_DATA, ignoreCase = true) -> {
|
||||
shares = readData(parser)
|
||||
}
|
||||
else -> {
|
||||
skip(parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
return shares
|
||||
@ -130,24 +134,25 @@ class ShareXMLParser {
|
||||
@Throws(XmlPullParserException::class, IOException::class)
|
||||
private fun readMeta(parser: XmlPullParser) {
|
||||
parser.require(XmlPullParser.START_TAG, ns, NODE_META)
|
||||
//Log_OC.d(TAG, "---- NODE META ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||
continue
|
||||
}
|
||||
val name = parser.name
|
||||
|
||||
if (name.equals(NODE_STATUS, ignoreCase = true)) {
|
||||
status = readNode(parser, NODE_STATUS)
|
||||
|
||||
} else if (name.equals(NODE_STATUS_CODE, ignoreCase = true)) {
|
||||
statusCode = Integer.parseInt(readNode(parser, NODE_STATUS_CODE))
|
||||
|
||||
} else if (name.equals(NODE_MESSAGE, ignoreCase = true)) {
|
||||
message = readNode(parser, NODE_MESSAGE)
|
||||
|
||||
} else {
|
||||
skip(parser)
|
||||
when {
|
||||
name.equals(NODE_STATUS, ignoreCase = true) -> {
|
||||
status = readNode(parser, NODE_STATUS)
|
||||
}
|
||||
name.equals(NODE_STATUS_CODE, ignoreCase = true) -> {
|
||||
statusCode = Integer.parseInt(readNode(parser, NODE_STATUS_CODE))
|
||||
}
|
||||
name.equals(NODE_MESSAGE, ignoreCase = true) -> {
|
||||
message = readNode(parser, NODE_MESSAGE)
|
||||
}
|
||||
else -> {
|
||||
skip(parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,33 +170,34 @@ class ShareXMLParser {
|
||||
var share: RemoteShare? = null
|
||||
|
||||
parser.require(XmlPullParser.START_TAG, ns, NODE_DATA)
|
||||
//Log_OC.d(TAG, "---- NODE DATA ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||
continue
|
||||
}
|
||||
val name = parser.name
|
||||
if (name.equals(NODE_ELEMENT, ignoreCase = true)) {
|
||||
readElement(parser, shares)
|
||||
|
||||
} else if (name.equals(NODE_ID, ignoreCase = true)) {// Parse Create XML Response
|
||||
share = RemoteShare()
|
||||
val value = readNode(parser, NODE_ID)
|
||||
share.id = Integer.parseInt(value).toLong()
|
||||
|
||||
} else if (name.equals(NODE_URL, ignoreCase = true)) {
|
||||
// NOTE: this field is received in all the public shares from OC 9.0.0
|
||||
// in previous versions, it's received in the result of POST requests, but not
|
||||
// in GET requests
|
||||
share!!.shareType = ShareType.PUBLIC_LINK
|
||||
val value = readNode(parser, NODE_URL)
|
||||
share.shareLink = value
|
||||
|
||||
} else if (name.equals(NODE_TOKEN, ignoreCase = true)) {
|
||||
share!!.token = readNode(parser, NODE_TOKEN)
|
||||
|
||||
} else {
|
||||
skip(parser)
|
||||
when {
|
||||
name.equals(NODE_ELEMENT, ignoreCase = true) -> {
|
||||
readElement(parser, shares)
|
||||
}
|
||||
name.equals(NODE_ID, ignoreCase = true) -> {// Parse Create XML Response
|
||||
share = RemoteShare()
|
||||
val value = readNode(parser, NODE_ID)
|
||||
share.id = Integer.parseInt(value).toLong()
|
||||
}
|
||||
name.equals(NODE_URL, ignoreCase = true) -> {
|
||||
// NOTE: this field is received in all the public shares from OC 9.0.0
|
||||
// in previous versions, it's received in the result of POST requests, but not
|
||||
// in GET requests
|
||||
share!!.shareType = ShareType.PUBLIC_LINK
|
||||
val value = readNode(parser, NODE_URL)
|
||||
share.shareLink = value
|
||||
}
|
||||
name.equals(NODE_TOKEN, ignoreCase = true) -> {
|
||||
share!!.token = readNode(parser, NODE_TOKEN)
|
||||
}
|
||||
else -> {
|
||||
skip(parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +223,6 @@ class ShareXMLParser {
|
||||
|
||||
val remoteShare = RemoteShare()
|
||||
|
||||
//Log_OC.d(TAG, "---- NODE ELEMENT ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||
continue
|
||||
@ -243,7 +248,7 @@ class ShareXMLParser {
|
||||
}
|
||||
|
||||
name.equals(NODE_ITEM_SOURCE, ignoreCase = true) -> {
|
||||
remoteShare.itemSource = java.lang.Long.parseLong(readNode(parser, NODE_ITEM_SOURCE))
|
||||
remoteShare.itemSource = readNode(parser, NODE_ITEM_SOURCE)
|
||||
}
|
||||
|
||||
name.equals(NODE_PARENT, ignoreCase = true) -> {
|
||||
@ -260,7 +265,7 @@ class ShareXMLParser {
|
||||
}
|
||||
|
||||
name.equals(NODE_FILE_SOURCE, ignoreCase = true) -> {
|
||||
remoteShare.fileSource = java.lang.Long.parseLong(readNode(parser, NODE_FILE_SOURCE))
|
||||
remoteShare.fileSource = readNode(parser, NODE_FILE_SOURCE)
|
||||
}
|
||||
|
||||
name.equals(NODE_PATH, ignoreCase = true) -> {
|
||||
@ -343,7 +348,6 @@ class ShareXMLParser {
|
||||
private fun readNode(parser: XmlPullParser, node: String): String {
|
||||
parser.require(XmlPullParser.START_TAG, ns, node)
|
||||
val value = readText(parser)
|
||||
//Log_OC.d(TAG, "node= " + node + ", value= " + value);
|
||||
parser.require(XmlPullParser.END_TAG, ns, node)
|
||||
return value
|
||||
}
|
||||
@ -387,8 +391,6 @@ class ShareXMLParser {
|
||||
|
||||
companion object {
|
||||
|
||||
//private static final String TAG = ShareXMLParser.class.getSimpleName();
|
||||
|
||||
// No namespaces
|
||||
private val ns: String? = null
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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
|
||||
@ -30,9 +30,9 @@ import com.owncloud.android.lib.common.http.HttpConstants
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PutMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.lib.resources.shares.RemoteShare.Companion.DEFAULT_PERMISSION
|
||||
import okhttp3.FormBody
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
@ -61,7 +61,6 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* Name to update in Share resource. Ignored by servers previous to version 10.0.0
|
||||
*
|
||||
* @param name Name to set to the target share.
|
||||
* Empty string clears the current name.
|
||||
* Null results in no update applied to the name.
|
||||
*/
|
||||
@ -70,7 +69,6 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* Password to update in Share resource.
|
||||
*
|
||||
* @param password Password to set to the target share.
|
||||
* Empty string clears the current password.
|
||||
* Null results in no update applied to the password.
|
||||
*/
|
||||
@ -79,7 +77,6 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* Expiration date to update in Share resource.
|
||||
*
|
||||
* @param expirationDateInMillis Expiration date to set to the target share.
|
||||
* A negative value clears the current expiration date.
|
||||
* Zero value (start-of-epoch) results in no update done on
|
||||
* the expiration date.
|
||||
@ -89,7 +86,6 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* Permissions to update in Share resource.
|
||||
*
|
||||
* @param permissions Permissions to set to the target share.
|
||||
* Values <= 0 result in no update applied to the permissions.
|
||||
*/
|
||||
var permissions: Int = DEFAULT_PERMISSION
|
||||
@ -97,7 +93,6 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* Enable upload permissions to update in Share resource.
|
||||
*
|
||||
* @param publicUpload Upload permission to set to the target share.
|
||||
* Null results in no update applied to the upload permission.
|
||||
*/
|
||||
var publicUpload: Boolean? = null
|
||||
@ -181,7 +176,7 @@ class UpdateRemoteShareOperation
|
||||
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Exception while Creating New Share", e)
|
||||
Timber.e(e, "Exception while Creating New Share")
|
||||
}
|
||||
|
||||
return result
|
||||
@ -190,7 +185,6 @@ class UpdateRemoteShareOperation
|
||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
private val TAG = GetRemoteShareOperation::class.java.simpleName
|
||||
|
||||
private const val PARAM_NAME = "name"
|
||||
private const val PARAM_PASSWORD = "password"
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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,
|
||||
@ -18,10 +18,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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(
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* 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,
|
||||
@ -18,7 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
@ -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.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ShareParserResult> = 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<ShareParserResult> =
|
||||
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<ShareParserResult> =
|
||||
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<ShareParserResult> =
|
||||
RemoveRemoteShareOperation(
|
||||
remoteId
|
||||
).execute(client)
|
||||
}
|
@ -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.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ArrayList<JSONObject>> =
|
||||
GetRemoteShareesOperation(
|
||||
searchString,
|
||||
page,
|
||||
perPage
|
||||
).execute(client)
|
||||
}
|
@ -2,7 +2,9 @@
|
||||
* @author masensio
|
||||
* @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* @author Abel García de Prada
|
||||
*
|
||||
* 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
|
||||
@ -24,7 +26,6 @@
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.status
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient
|
||||
@ -33,10 +34,14 @@ 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.common.utils.Log_OC
|
||||
import org.json.JSONObject
|
||||
import com.owncloud.android.lib.resources.response.CapabilityResponse
|
||||
import com.owncloud.android.lib.resources.response.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
|
||||
import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBooleanType
|
||||
|
||||
/**
|
||||
* Get the Capabilities from the server
|
||||
@ -45,228 +50,51 @@ import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBool
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
|
||||
|
||||
override fun run(client: OwnCloudClient): RemoteOperationResult<RemoteCapability> {
|
||||
var result: RemoteOperationResult<RemoteCapability>
|
||||
|
||||
try {
|
||||
val requestUri = client.baseUri
|
||||
val uriBuilder = requestUri.buildUpon()
|
||||
uriBuilder.appendEncodedPath(OCS_ROUTE) // avoid starting "/" in this method
|
||||
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||
|
||||
val getMethod = GetMethod(URL(uriBuilder.build().toString()))
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||
|
||||
val uriBuilder = client.baseUri.buildUpon().apply {
|
||||
appendEncodedPath(OCS_ROUTE) // avoid starting "/" in this method
|
||||
appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||
}
|
||||
val getMethod = GetMethod(URL(uriBuilder.build().toString())).apply {
|
||||
addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||
}
|
||||
val status = client.executeHttpMethod(getMethod)
|
||||
|
||||
val response = getMethod.responseBodyAsString
|
||||
|
||||
if (!isSuccess(status)) {
|
||||
result = RemoteOperationResult(getMethod)
|
||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ")
|
||||
if (response != null) {
|
||||
Log_OC.e(TAG, "*** status code: $status; response message: $response")
|
||||
} else {
|
||||
Log_OC.e(TAG, "*** status code: $status")
|
||||
}
|
||||
if (status == HttpConstants.HTTP_OK) {
|
||||
Timber.d("Successful response $response")
|
||||
|
||||
return result
|
||||
}
|
||||
// Parse the response
|
||||
val moshi: Moshi = Moshi.Builder().build()
|
||||
val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, CapabilityResponse::class.java)
|
||||
val adapter: JsonAdapter<CommonOcsResponse<CapabilityResponse>> = moshi.adapter(type)
|
||||
val commonResponse: CommonOcsResponse<CapabilityResponse>? = adapter.fromJson(response)
|
||||
|
||||
Log_OC.d(TAG, "Successful response: " + response!!)
|
||||
|
||||
// Parse the response
|
||||
val respJSON = JSONObject(response)
|
||||
val respOCS = respJSON.getJSONObject(NODE_OCS)
|
||||
val respMeta = respOCS.getJSONObject(NODE_META)
|
||||
val respData = respOCS.getJSONObject(NODE_DATA)
|
||||
|
||||
// Read meta
|
||||
val statusProp = respMeta.getString(PROPERTY_STATUS).equals(PROPERTY_STATUS_OK, ignoreCase = true)
|
||||
val statuscode = respMeta.getInt(PROPERTY_STATUSCODE)
|
||||
val message = respMeta.getString(PROPERTY_MESSAGE)
|
||||
|
||||
if (statusProp) {
|
||||
val capability = RemoteCapability()
|
||||
// Add Version
|
||||
if (respData.has(NODE_VERSION)) {
|
||||
val respVersion = respData.getJSONObject(NODE_VERSION)
|
||||
capability.versionMayor = respVersion.getInt(PROPERTY_MAJOR)
|
||||
capability.versionMinor = respVersion.getInt(PROPERTY_MINOR)
|
||||
capability.versionMicro = respVersion.getInt(PROPERTY_MICRO)
|
||||
capability.versionString = respVersion.getString(PROPERTY_STRING)
|
||||
capability.versionEdition = respVersion.getString(PROPERTY_EDITION)
|
||||
Log_OC.d(TAG, "*** Added $NODE_VERSION")
|
||||
}
|
||||
|
||||
// Capabilities Object
|
||||
if (respData.has(NODE_CAPABILITIES)) {
|
||||
val respCapabilities = respData.getJSONObject(NODE_CAPABILITIES)
|
||||
|
||||
// Add Core: pollinterval
|
||||
if (respCapabilities.has(NODE_CORE)) {
|
||||
val respCore = respCapabilities.getJSONObject(NODE_CORE)
|
||||
capability.corePollinterval = respCore.getInt(PROPERTY_POLLINTERVAL)
|
||||
Log_OC.d(TAG, "*** Added $NODE_CORE")
|
||||
}
|
||||
|
||||
// Add files_sharing: public, user, resharing
|
||||
if (respCapabilities.has(NODE_FILES_SHARING)) {
|
||||
val respFilesSharing = respCapabilities.getJSONObject(NODE_FILES_SHARING)
|
||||
if (respFilesSharing.has(PROPERTY_API_ENABLED)) {
|
||||
capability.filesSharingApiEnabled = CapabilityBooleanType.fromBooleanValue(
|
||||
respFilesSharing.getBoolean(PROPERTY_API_ENABLED)
|
||||
)
|
||||
}
|
||||
if (respFilesSharing.has(PROPERTY_SEARCH_MIN_LENGTH)){
|
||||
capability.filesSharingSearchMinLength = respFilesSharing.getInt(
|
||||
PROPERTY_SEARCH_MIN_LENGTH)
|
||||
}
|
||||
|
||||
if (respFilesSharing.has(NODE_PUBLIC)) {
|
||||
val respPublic = respFilesSharing.getJSONObject(NODE_PUBLIC)
|
||||
capability.filesSharingPublicEnabled = CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_ENABLED)
|
||||
)
|
||||
|
||||
if (respPublic.has(NODE_PASSWORD)) {
|
||||
val respPassword = respPublic.getJSONObject(NODE_PASSWORD)
|
||||
capability.filesSharingPublicPasswordEnforced =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getJSONObject(NODE_PASSWORD).getBoolean(PROPERTY_ENFORCED)
|
||||
)
|
||||
|
||||
if (respPassword.has(NODE_ENFORCED_FOR)) {
|
||||
capability.filesSharingPublicPasswordEnforcedReadOnly =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPassword.getJSONObject(NODE_ENFORCED_FOR).getBoolean(
|
||||
PROPERTY_ENFORCED_READ_ONLY
|
||||
)
|
||||
)
|
||||
|
||||
capability.filesSharingPublicPasswordEnforcedReadWrite =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPassword.getJSONObject(NODE_ENFORCED_FOR).getBoolean(
|
||||
PROPERTY_ENFORCED_READ_WRITE
|
||||
)
|
||||
)
|
||||
|
||||
capability.filesSharingPublicPasswordEnforcedUploadOnly =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPassword.getJSONObject(NODE_ENFORCED_FOR).getBoolean(
|
||||
PROPERTY_ENFORCED_UPLOAD_ONLY
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (respPublic.has(NODE_EXPIRE_DATE)) {
|
||||
val respExpireDate = respPublic.getJSONObject(NODE_EXPIRE_DATE)
|
||||
capability.filesSharingPublicExpireDateEnabled =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respExpireDate.getBoolean(PROPERTY_ENABLED)
|
||||
)
|
||||
if (respExpireDate.has(PROPERTY_DAYS)) {
|
||||
capability.filesSharingPublicExpireDateDays =
|
||||
respExpireDate.getInt(PROPERTY_DAYS)
|
||||
}
|
||||
if (respExpireDate.has(PROPERTY_ENFORCED)) {
|
||||
capability.filesSharingPublicExpireDateEnforced =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respExpireDate.getBoolean(PROPERTY_ENFORCED)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (respPublic.has(PROPERTY_UPLOAD)) {
|
||||
capability.filesSharingPublicUpload = CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_UPLOAD)
|
||||
)
|
||||
}
|
||||
if (respPublic.has(PROPERTY_UPLOAD_ONLY)) {
|
||||
capability.filesSharingPublicSupportsUploadOnly =
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_UPLOAD_ONLY)
|
||||
)
|
||||
}
|
||||
if (respPublic.has(PROPERTY_MULTIPLE)) {
|
||||
capability.filesSharingPublicMultiple = CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_MULTIPLE)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (respFilesSharing.has(NODE_USER)) {
|
||||
val respUser = respFilesSharing.getJSONObject(NODE_USER)
|
||||
capability.filesSharingUserSendMail = CapabilityBooleanType.fromBooleanValue(
|
||||
respUser.getBoolean(PROPERTY_SEND_MAIL)
|
||||
)
|
||||
}
|
||||
|
||||
capability.filesSharingResharing = CapabilityBooleanType.fromBooleanValue(
|
||||
respFilesSharing.getBoolean(PROPERTY_RESHARING)
|
||||
)
|
||||
if (respFilesSharing.has(NODE_FEDERATION)) {
|
||||
val respFederation = respFilesSharing.getJSONObject(NODE_FEDERATION)
|
||||
capability.filesSharingFederationOutgoing =
|
||||
CapabilityBooleanType.fromBooleanValue(respFederation.getBoolean(PROPERTY_OUTGOING))
|
||||
capability.filesSharingFederationIncoming = CapabilityBooleanType.fromBooleanValue(
|
||||
respFederation.getBoolean(PROPERTY_INCOMING)
|
||||
)
|
||||
}
|
||||
Log_OC.d(TAG, "*** Added $NODE_FILES_SHARING")
|
||||
}
|
||||
|
||||
if (respCapabilities.has(NODE_FILES)) {
|
||||
val respFiles = respCapabilities.getJSONObject(NODE_FILES)
|
||||
// Add files
|
||||
capability.filesBigFileChunking = CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_BIGFILECHUNKING)
|
||||
)
|
||||
if (respFiles.has(PROPERTY_UNDELETE)) {
|
||||
capability.filesUndelete = CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_UNDELETE)
|
||||
)
|
||||
}
|
||||
if (respFiles.has(PROPERTY_VERSIONING)) {
|
||||
capability.filesVersioning = CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_VERSIONING)
|
||||
)
|
||||
}
|
||||
Log_OC.d(TAG, "*** Added $NODE_FILES")
|
||||
}
|
||||
}
|
||||
// Result
|
||||
result = RemoteOperationResult(OK)
|
||||
result.data = capability
|
||||
result.data = commonResponse?.ocs?.data?.toRemoteCapability()
|
||||
|
||||
Log_OC.d(TAG, "*** Get Capabilities completed ")
|
||||
Timber.d("Get Capabilities completed and parsed to ${result.data}")
|
||||
} else {
|
||||
result = RemoteOperationResult(statuscode, message, null)
|
||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ")
|
||||
Log_OC.e(TAG, "*** status: $statusProp; message: $message")
|
||||
result = RemoteOperationResult(getMethod)
|
||||
Timber.e("Failed response while getting capabilities from the server status code: $status; response message: $response")
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Log_OC.e(TAG, "Exception while getting capabilities", e)
|
||||
Timber.e(e, "Exception while getting capabilities")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun isSuccess(status: Int): Boolean {
|
||||
return status == HttpConstants.HTTP_OK
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = GetRemoteCapabilitiesOperation::class.java.simpleName
|
||||
|
||||
// OCS Routes
|
||||
private const val OCS_ROUTE = "ocs/v2.php/cloud/capabilities"
|
||||
|
||||
@ -275,58 +103,5 @@ class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
|
||||
|
||||
// Arguments - constant values
|
||||
private const val VALUE_FORMAT = "json"
|
||||
|
||||
// JSON Node names
|
||||
private const val NODE_OCS = "ocs"
|
||||
|
||||
private const val NODE_META = "meta"
|
||||
|
||||
private const val NODE_DATA = "data"
|
||||
private const val NODE_VERSION = "version"
|
||||
|
||||
private const val NODE_CAPABILITIES = "capabilities"
|
||||
private const val NODE_CORE = "core"
|
||||
|
||||
private const val NODE_FILES_SHARING = "files_sharing"
|
||||
private const val NODE_PUBLIC = "public"
|
||||
private const val NODE_PASSWORD = "password"
|
||||
private const val NODE_ENFORCED_FOR = "enforced_for"
|
||||
private const val NODE_EXPIRE_DATE = "expire_date"
|
||||
private const val NODE_USER = "user"
|
||||
private const val NODE_FEDERATION = "federation"
|
||||
private const val NODE_FILES = "files"
|
||||
|
||||
private const val PROPERTY_STATUS = "status"
|
||||
private const val PROPERTY_STATUS_OK = "ok"
|
||||
private const val PROPERTY_STATUSCODE = "statuscode"
|
||||
private const val PROPERTY_MESSAGE = "message"
|
||||
|
||||
private const val PROPERTY_POLLINTERVAL = "pollinterval"
|
||||
|
||||
private const val PROPERTY_MAJOR = "major"
|
||||
private const val PROPERTY_MINOR = "minor"
|
||||
private const val PROPERTY_MICRO = "micro"
|
||||
private const val PROPERTY_STRING = "string"
|
||||
private const val PROPERTY_EDITION = "edition"
|
||||
|
||||
private const val PROPERTY_API_ENABLED = "api_enabled"
|
||||
private const val PROPERTY_ENABLED = "enabled"
|
||||
private const val PROPERTY_ENFORCED = "enforced"
|
||||
private const val PROPERTY_ENFORCED_READ_ONLY = "read_only"
|
||||
private const val PROPERTY_ENFORCED_READ_WRITE = "read_write"
|
||||
private const val PROPERTY_ENFORCED_UPLOAD_ONLY = "upload_only"
|
||||
private const val PROPERTY_DAYS = "days"
|
||||
private const val PROPERTY_SEARCH_MIN_LENGTH = "search_min_length"
|
||||
private const val PROPERTY_SEND_MAIL = "send_mail"
|
||||
private const val PROPERTY_UPLOAD = "upload"
|
||||
private const val PROPERTY_UPLOAD_ONLY = "supports_upload_only"
|
||||
private const val PROPERTY_MULTIPLE = "multiple"
|
||||
private const val PROPERTY_RESHARING = "resharing"
|
||||
private const val PROPERTY_OUTGOING = "outgoing"
|
||||
private const val PROPERTY_INCOMING = "incoming"
|
||||
|
||||
private const val PROPERTY_BIGFILECHUNKING = "bigfilechunking"
|
||||
private const val PROPERTY_UNDELETE = "undelete"
|
||||
private const val PROPERTY_VERSIONING = "versioning"
|
||||
}
|
||||
}
|
||||
|
@ -1,200 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 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 com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
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<OwnCloudVersion> {
|
||||
|
||||
/**
|
||||
* 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 TAG = GetRemoteStatusOperation.class.getSimpleName();
|
||||
|
||||
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<OwnCloudVersion> 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()) {
|
||||
Log_OC.i(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage());
|
||||
|
||||
} else if (mLatestResult.getException() != null) {
|
||||
Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(),
|
||||
mLatestResult.getException());
|
||||
|
||||
} else {
|
||||
Log_OC.e(TAG, "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<OwnCloudVersion> 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()) {
|
||||
Log_OC.d(TAG, "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);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user