mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-12 02:16:20 +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)
|
# Local configuration files (sdk path, etc)
|
||||||
.gradle/
|
.gradle/
|
||||||
local.properties
|
local.properties
|
||||||
sample_client/local.properties
|
|
||||||
|
|
||||||
# Mac .DS_Store files
|
# Mac .DS_Store files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Proguard README
|
|
||||||
proguard-project.txt
|
|
||||||
sample_client/proguard-project.txt
|
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
ownCloud Android Library is available under MIT license
|
ownCloud Android Library is available under MIT license
|
||||||
|
|
||||||
Copyright (C) 2019 ownCloud GmbH.
|
Copyright (C) 2020 ownCloud GmbH.
|
||||||
Copyright (C) 2012 Bartek Przybylski
|
Copyright (C) 2012 Bartek Przybylski
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
// Libraries
|
kotlinVersion = '1.3.72'
|
||||||
kotlinVersion = '1.3.50'
|
moshiVersion = "1.9.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -9,7 +9,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
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-gradle-plugin:$kotlinVersion"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-allopen:$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
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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'
|
api 'com.squareup.okhttp3:okhttp:3.12.0'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||||
api 'com.gitlab.ownclouders:dav4android:oc_support_1.0.1'
|
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 {
|
allOpen {
|
||||||
@ -19,11 +26,15 @@ android {
|
|||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 19
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
|
|
||||||
versionCode = 10000400
|
versionCode = 10000500
|
||||||
versionName = "1.0.4"
|
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 {
|
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
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2019 ownCloud GmbH.
|
* Copyright (C) 2020 ownCloud GmbH.
|
||||||
* Copyright (C) 2012 Bartek Przybylski
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* 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.HttpConstants;
|
||||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
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.common.utils.RandomUtils;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
import okhttp3.Cookie;
|
import okhttp3.Cookie;
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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 class OwnCloudClient extends HttpClient {
|
||||||
|
|
||||||
public static final String WEBDAV_FILES_PATH_4_0 = "/remote.php/dav/files/";
|
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 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_REDIRECTIONS_COUNT = 3;
|
||||||
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
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 OwnCloudVersion mVersion = null;
|
||||||
private OwnCloudAccount mAccount;
|
private OwnCloudAccount mAccount;
|
||||||
|
|
||||||
/**
|
private SingleSessionManager mSingleSessionManager = null;
|
||||||
* {@link @OwnCloudClientManager} holding a reference to this object and delivering it to callers; might be
|
|
||||||
* NULL
|
|
||||||
*/
|
|
||||||
private OwnCloudClientManager mOwnCloudClientManager = null;
|
|
||||||
|
|
||||||
private String mRedirectedLocation;
|
|
||||||
private boolean mFollowRedirects;
|
private boolean mFollowRedirects;
|
||||||
|
|
||||||
public OwnCloudClient(Uri baseUri) {
|
public OwnCloudClient(Uri baseUri) {
|
||||||
@ -86,7 +79,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
mBaseUri = baseUri;
|
mBaseUri = baseUri;
|
||||||
|
|
||||||
mInstanceNumber = sIntanceCounter++;
|
mInstanceNumber = sIntanceCounter++;
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
|
Timber.d("#" + mInstanceNumber + "Creating OwnCloudClient");
|
||||||
|
|
||||||
clearCredentials();
|
clearCredentials();
|
||||||
clearCookies();
|
clearCookies();
|
||||||
@ -99,7 +92,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
mCredentials.applyTo(this);
|
mCredentials.applyTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyCredentials() {
|
void applyCredentials() {
|
||||||
mCredentials.applyTo(this);
|
mCredentials.applyTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +105,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
setRequestId(method);
|
setRequestId(method);
|
||||||
|
|
||||||
status = method.execute();
|
status = method.execute();
|
||||||
checkFirstRedirection(method);
|
|
||||||
|
|
||||||
if (mFollowRedirects) {
|
if (mFollowRedirects) {
|
||||||
status = followRedirection(method).getLastStatus();
|
status = followRedirection(method).getLastStatus();
|
||||||
@ -127,13 +119,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
return status;
|
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 {
|
private int executeRedirectedHttpMethod(HttpBaseMethod method) throws Exception {
|
||||||
boolean repeatWithFreshCredentials;
|
boolean repeatWithFreshCredentials;
|
||||||
int repeatCounter = 0;
|
int repeatCounter = 0;
|
||||||
@ -163,7 +148,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
// Header to allow tracing requests in apache and ownCloud logs
|
// Header to allow tracing requests in apache and ownCloud logs
|
||||||
addHeaderForAllRequests(OC_X_REQUEST_ID, requestId);
|
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 {
|
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_PERMANENTLY ||
|
||||||
status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
||||||
status == HttpConstants.HTTP_TEMPORARY_REDIRECT)
|
status == HttpConstants.HTTP_TEMPORARY_REDIRECT)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null
|
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null
|
||||||
? method.getResponseHeader(HttpConstants.LOCATION_HEADER)
|
? method.getResponseHeader(HttpConstants.LOCATION_HEADER)
|
||||||
: method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
: method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||||
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
Timber.d("#" + mInstanceNumber + "Location to redirect: " + location);
|
||||||
"Location to redirect: " + location);
|
|
||||||
|
|
||||||
redirectionPath.addLocation(location);
|
redirectionPath.addLocation(location);
|
||||||
|
|
||||||
@ -216,7 +200,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
redirectionsCount++;
|
redirectionsCount++;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No location to redirect!");
|
Timber.d(" #" + mInstanceNumber + "No location to redirect!");
|
||||||
status = HttpConstants.HTTP_NOT_FOUND;
|
status = HttpConstants.HTTP_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,8 +221,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
responseBodyAsStream.close();
|
responseBodyAsStream.close();
|
||||||
|
|
||||||
} catch (IOException io) {
|
} catch (IOException io) {
|
||||||
Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response;" +
|
Timber.e(io, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED");
|
||||||
" will be IGNORED", io);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,7 +231,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri getUserFilesWebDavUri() {
|
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)
|
||||||
: Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId(
|
: Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId(
|
||||||
mAccount.getSavedAccount(), getContext()
|
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() {
|
public String getCookiesString() {
|
||||||
StringBuilder cookiesString = new StringBuilder();
|
StringBuilder cookiesString = new StringBuilder();
|
||||||
List<Cookie> cookieList = getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()));
|
List<Cookie> cookieList = getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()));
|
||||||
@ -384,7 +335,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
if (invalidated) {
|
if (invalidated) {
|
||||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mAccount.loadCredentials(getContext());
|
mAccount.loadCredentials(getContext());
|
||||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||||
@ -392,18 +342,16 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
credentialsWereRefreshed = true;
|
credentialsWereRefreshed = true;
|
||||||
|
|
||||||
} catch (AccountsException | IOException e) {
|
} catch (AccountsException | IOException e) {
|
||||||
Log_OC.e(
|
Timber.e(e, "Error while trying to refresh auth token for %s",
|
||||||
TAG,
|
mAccount.getSavedAccount().name
|
||||||
"Error while trying to refresh auth token for " + mAccount.getSavedAccount().name,
|
|
||||||
e
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!credentialsWereRefreshed && mOwnCloudClientManager != null) {
|
if (!credentialsWereRefreshed && mSingleSessionManager != null) {
|
||||||
// if credentials are not refreshed, client must be removed
|
// if credentials are not refreshed, client must be removed
|
||||||
// from the OwnCloudClientManager to prevent it is reused once and again
|
// from the OwnCloudClientManager to prevent it is reused once and again
|
||||||
mOwnCloudClientManager.removeClientFor(mAccount);
|
mSingleSessionManager.removeClientFor(mAccount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else: onExecute will finish with status 401
|
// else: onExecute will finish with status 401
|
||||||
@ -421,21 +369,21 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
* cannot be invalidated with the given arguments.
|
* cannot be invalidated with the given arguments.
|
||||||
*/
|
*/
|
||||||
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
||||||
|
boolean shouldInvalidateAccountCredentials =
|
||||||
|
(httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED);
|
||||||
|
|
||||||
boolean should = (httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED); // invalid credentials
|
shouldInvalidateAccountCredentials &= (mCredentials != null && // real credentials
|
||||||
|
|
||||||
should &= (mCredentials != null && // real credentials
|
|
||||||
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
||||||
|
|
||||||
// test if have all the needed to effectively invalidate ...
|
// 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
|
* 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>
|
* <p>
|
||||||
* {@link #shouldInvalidateAccountCredentials(int)} should be called first.
|
* {@link #shouldInvalidateAccountCredentials(int)} should be called first.
|
||||||
*
|
*
|
||||||
@ -451,14 +399,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OwnCloudClientManager getOwnCloudClientManager() {
|
|
||||||
return mOwnCloudClientManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOwnCloudClientManager(OwnCloudClientManager clientManager) {
|
|
||||||
mOwnCloudClientManager = clientManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean followRedirects() {
|
public boolean followRedirects() {
|
||||||
return mFollowRedirects;
|
return mFollowRedirects;
|
||||||
}
|
}
|
||||||
@ -466,4 +406,4 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
public void setFollowRedirects(boolean followRedirects) {
|
public void setFollowRedirects(boolean followRedirects) {
|
||||||
this.mFollowRedirects = followRedirects;
|
this.mFollowRedirects = followRedirects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -29,8 +29,6 @@ import android.net.Uri;
|
|||||||
|
|
||||||
public class OwnCloudClientFactory {
|
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
|
* Creates a OwnCloudClient to access a URL and sets the desired parameters for ownCloud
|
||||||
* client connections.
|
* client connections.
|
||||||
@ -39,8 +37,7 @@ public class OwnCloudClientFactory {
|
|||||||
* @param context Android context where the OwnCloudClient is being created.
|
* @param context Android context where the OwnCloudClient is being created.
|
||||||
* @return A OwnCloudClient object ready to be used
|
* @return A OwnCloudClient object ready to be used
|
||||||
*/
|
*/
|
||||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
|
||||||
boolean followRedirects) {
|
|
||||||
OwnCloudClient client = new OwnCloudClient(uri);
|
OwnCloudClient client = new OwnCloudClient(uri);
|
||||||
|
|
||||||
client.setFollowRedirects(followRedirects);
|
client.setFollowRedirects(followRedirects);
|
||||||
@ -49,4 +46,4 @@ public class OwnCloudClientFactory {
|
|||||||
|
|
||||||
return client;
|
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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.accounts.OperationCanceledException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||||
import com.owncloud.android.lib.common.http.HttpClient;
|
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.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -42,31 +41,39 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link OwnCloudClientManager}
|
|
||||||
* <p>
|
|
||||||
* TODO check multithreading safety
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
* @author Christian Schabesberger
|
* @author Christian Schabesberger
|
||||||
* @author David González Verdugo
|
* @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> mClientsWithKnownUsername = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername = 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,
|
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
|
||||||
AuthenticatorException, IOException {
|
AuthenticatorException, IOException {
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
Timber.d("getClientFor starting ");
|
||||||
Log_OC.d(TAG, "getClientFor starting ");
|
|
||||||
}
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account");
|
throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account");
|
||||||
}
|
}
|
||||||
@ -84,21 +91,16 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
if (accountName != null) {
|
if (accountName != null) {
|
||||||
client = mClientsWithUnknownUsername.remove(sessionName);
|
client = mClientsWithUnknownUsername.remove(sessionName);
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("reusing client for session %s", sessionName);
|
||||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
|
||||||
}
|
|
||||||
mClientsWithKnownUsername.put(accountName, client);
|
mClientsWithKnownUsername.put(accountName, client);
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("moved client to account %s", accountName);
|
||||||
Log_OC.v(TAG, "moved client to account " + accountName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client = mClientsWithUnknownUsername.get(sessionName);
|
client = mClientsWithUnknownUsername.get(sessionName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("reusing client for account %s", accountName);
|
||||||
Log_OC.v(TAG, "reusing client for account " + accountName);
|
|
||||||
}
|
|
||||||
reusingKnown = true;
|
reusingKnown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,47 +112,36 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
true); // TODO remove dependency on OwnCloudClientFactory
|
true); // TODO remove dependency on OwnCloudClientFactory
|
||||||
client.setAccount(account);
|
client.setAccount(account);
|
||||||
HttpClient.setContext(context);
|
HttpClient.setContext(context);
|
||||||
client.setOwnCloudClientManager(this);
|
|
||||||
|
|
||||||
account.loadCredentials(context);
|
account.loadCredentials(context);
|
||||||
client.setCredentials(account.getCredentials());
|
client.setCredentials(account.getCredentials());
|
||||||
|
|
||||||
if (accountName != null) {
|
if (accountName != null) {
|
||||||
mClientsWithKnownUsername.put(accountName, client);
|
mClientsWithKnownUsername.put(accountName, client);
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("new client for account %s", accountName);
|
||||||
Log_OC.v(TAG, "new client for account " + accountName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mClientsWithUnknownUsername.put(sessionName, client);
|
mClientsWithUnknownUsername.put(sessionName, client);
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("new client for session %s", sessionName);
|
||||||
Log_OC.v(TAG, "new client for session " + sessionName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!reusingKnown && Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (!reusingKnown) {
|
||||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
Timber.v("reusing client for session %s", sessionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
keepCredentialsUpdated(client);
|
keepCredentialsUpdated(client);
|
||||||
keepCookiesUpdated(context, account, client);
|
keepCookiesUpdated(context, account, client);
|
||||||
keepUriUpdated(account, client);
|
keepUriUpdated(account, client);
|
||||||
}
|
}
|
||||||
|
Timber.d("getClientFor finishing ");
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log_OC.d(TAG, "getClientFor finishing ");
|
|
||||||
}
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void removeClientFor(OwnCloudAccount account) {
|
||||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
Timber.d("removeClientFor starting ");
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log_OC.d(TAG, "removeClientFor starting ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnCloudClient client;
|
OwnCloudClient client;
|
||||||
@ -158,31 +149,20 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
if (accountName != null) {
|
if (accountName != null) {
|
||||||
client = mClientsWithKnownUsername.remove(accountName);
|
client = mClientsWithKnownUsername.remove(accountName);
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("Removed client for account %s", accountName);
|
||||||
Log_OC.v(TAG, "Removed client for account " + accountName);
|
return;
|
||||||
}
|
|
||||||
return client;
|
|
||||||
} else {
|
} else {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
Timber.v("No client tracked for account %s", accountName);
|
||||||
Log_OC.v(TAG, "No client tracked for account " + accountName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mClientsWithUnknownUsername.clear();
|
mClientsWithUnknownUsername.clear();
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
Timber.d("removeClientFor finishing ");
|
||||||
Log_OC.d(TAG, "removeClientFor finishing ");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveAllClients(Context context, String accountType) {
|
public void saveAllClients(Context context, String accountType) {
|
||||||
|
Timber.d("Saving sessions... ");
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log_OC.d(TAG, "Saving sessions... ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<String> accountNames = mClientsWithKnownUsername.keySet().iterator();
|
Iterator<String> accountNames = mClientsWithKnownUsername.keySet().iterator();
|
||||||
String accountName;
|
String accountName;
|
||||||
@ -193,9 +173,7 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
AccountUtils.saveClient(mClientsWithKnownUsername.get(accountName), account, context);
|
AccountUtils.saveClient(mClientsWithKnownUsername.get(accountName), account, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
Timber.d("All sessions saved");
|
||||||
Log_OC.d(TAG, "All sessions saved");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
|
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2019 ownCloud GmbH.
|
* Copyright (C) 2020 ownCloud GmbH.
|
||||||
* Copyright (C) 2012 Bartek Przybylski
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* 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.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
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.files.FileUtils;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
import okhttp3.Cookie;
|
import okhttp3.Cookie;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AccountUtils {
|
public class AccountUtils {
|
||||||
|
|
||||||
private static final String TAG = AccountUtils.class.getSimpleName();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs full url to host and webdav resource basing on host version
|
* 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
|
webDavUrlForAccount = getBaseUrlForAccount(context, account) + OwnCloudClient.WEBDAV_FILES_PATH_4_0
|
||||||
+ ownCloudCredentials.getUsername();
|
+ ownCloudCredentials.getUsername();
|
||||||
} catch (OperationCanceledException | AuthenticatorException | IOException e) {
|
} catch (OperationCanceledException | AuthenticatorException | IOException e) {
|
||||||
e.printStackTrace();
|
Timber.e(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return webDavUrlForAccount;
|
return webDavUrlForAccount;
|
||||||
@ -104,7 +101,7 @@ public class AccountUtils {
|
|||||||
try {
|
try {
|
||||||
username = account.name.substring(0, account.name.lastIndexOf('@'));
|
username = account.name.substring(0, account.name.lastIndexOf('@'));
|
||||||
} catch (Exception e) {
|
} 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;
|
return username;
|
||||||
}
|
}
|
||||||
@ -124,7 +121,7 @@ public class AccountUtils {
|
|||||||
version = new OwnCloudVersion(versionString);
|
version = new OwnCloudVersion(versionString);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} 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;
|
return version;
|
||||||
}
|
}
|
||||||
@ -142,10 +139,9 @@ public class AccountUtils {
|
|||||||
AccountManager am = AccountManager.get(context);
|
AccountManager am = AccountManager.get(context);
|
||||||
|
|
||||||
String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
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);
|
String username = AccountUtils.getUsernameForAccount(account);
|
||||||
OwnCloudVersion version = new OwnCloudVersion(am.getUserData(account, Constants.KEY_OC_VERSION));
|
|
||||||
|
|
||||||
if (isOauth2) {
|
if (isOauth2) {
|
||||||
String accessToken = am.blockingGetAuthToken(
|
String accessToken = am.blockingGetAuthToken(
|
||||||
@ -154,7 +150,6 @@ public class AccountUtils {
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
|
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
String password = am.blockingGetAuthToken(
|
String password = am.blockingGetAuthToken(
|
||||||
account,
|
account,
|
||||||
@ -163,8 +158,7 @@ public class AccountUtils {
|
|||||||
|
|
||||||
credentials = OwnCloudCredentialsFactory.newBasicCredentials(
|
credentials = OwnCloudCredentialsFactory.newBasicCredentials(
|
||||||
username,
|
username,
|
||||||
password,
|
password
|
||||||
version.isPreemptiveAuthenticationPreferred()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,9 +197,8 @@ public class AccountUtils {
|
|||||||
if (url.contains("://")) {
|
if (url.contains("://")) {
|
||||||
url = url.substring(serverBaseUrl.toString().indexOf("://") + 3);
|
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) {
|
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
||||||
@ -216,7 +209,7 @@ public class AccountUtils {
|
|||||||
String cookiesString = client.getCookiesString();
|
String cookiesString = client.getCookiesString();
|
||||||
if (!"".equals(cookiesString)) {
|
if (!"".equals(cookiesString)) {
|
||||||
ac.setUserData(savedAccount, Constants.KEY_COOKIES, 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) {
|
public static void restoreCookies(Account account, OwnCloudClient client, Context context) {
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
Log_OC.d(TAG, "Cannot restore cookie for null account");
|
Timber.d("Cannot restore cookie for null account");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log_OC.d(TAG, "Restoring cookies for " + account.name);
|
Timber.d("Restoring cookies for %s", account.name);
|
||||||
|
|
||||||
// Account Manager
|
// Account Manager
|
||||||
AccountManager am = AccountManager.get(context.getApplicationContext());
|
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.
|
* 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 KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
|
||||||
|
|
||||||
|
public static final String OAUTH_SUPPORTED_TRUE = "TRUE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OC account cookies
|
* OC account cookies
|
||||||
*/
|
*/
|
||||||
@ -321,9 +318,6 @@ public class AccountUtils {
|
|||||||
*/
|
*/
|
||||||
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
||||||
|
|
||||||
/**
|
public static final int ACCOUNT_VERSION = 1;
|
||||||
* OAuth2 refresh token
|
|
||||||
**/
|
|
||||||
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -31,8 +31,6 @@ import okhttp3.internal.Util;
|
|||||||
|
|
||||||
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
private static final String TAG = OwnCloudCredentials.class.getSimpleName();
|
|
||||||
|
|
||||||
private String mUsername;
|
private String mUsername;
|
||||||
private String mPassword;
|
private String mPassword;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -38,12 +38,6 @@ public class OwnCloudCredentialsFactory {
|
|||||||
return new OwnCloudBasicCredentials(username, password);
|
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) {
|
public static OwnCloudCredentials newBearerCredentials(String username, String authToken) {
|
||||||
return new OwnCloudBearerCredentials(username, 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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.content.Context;
|
||||||
|
|
||||||
import android.os.Build;
|
import com.owncloud.android.lib.common.SingleSessionManager;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
|
||||||
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
|
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
|
||||||
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
|
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
|
||||||
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
||||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
import okhttp3.Cookie;
|
import okhttp3.Cookie;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Protocol;
|
import okhttp3.Protocol;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
@ -58,8 +57,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class HttpClient {
|
public class HttpClient {
|
||||||
private static final String TAG = HttpClient.class.toString();
|
|
||||||
|
|
||||||
private static OkHttpClient sOkHttpClient;
|
private static OkHttpClient sOkHttpClient;
|
||||||
private static HttpInterceptor sOkHttpInterceptor;
|
private static HttpInterceptor sOkHttpInterceptor;
|
||||||
private static Context sContext;
|
private static Context sContext;
|
||||||
@ -77,10 +74,10 @@ public class HttpClient {
|
|||||||
sslContext = SSLContext.getInstance("TLSv1.2");
|
sslContext = SSLContext.getInstance("TLSv1.2");
|
||||||
} catch (NoSuchAlgorithmException tlsv12Exception) {
|
} catch (NoSuchAlgorithmException tlsv12Exception) {
|
||||||
try {
|
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");
|
sslContext = SSLContext.getInstance("TLSv1.1");
|
||||||
} catch (NoSuchAlgorithmException tlsv11Exception) {
|
} 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");
|
sslContext = SSLContext.getInstance("TLSv1");
|
||||||
// should be available in any device; see reference of supported protocols in
|
// should be available in any device; see reference of supported protocols in
|
||||||
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
||||||
@ -91,22 +88,15 @@ public class HttpClient {
|
|||||||
|
|
||||||
SSLSocketFactory sslSocketFactory;
|
SSLSocketFactory sslSocketFactory;
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
|
sslSocketFactory = sslContext.getSocketFactory();
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Automatic cookie handling, NOT PERSISTENT
|
// Automatic cookie handling, NOT PERSISTENT
|
||||||
CookieJar cookieJar = new CookieJar() {
|
CookieJar cookieJar = new CookieJar() {
|
||||||
@Override
|
@Override
|
||||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||||
// Avoid duplicated cookies
|
// Avoid duplicated cookies
|
||||||
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>();
|
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>(cookies);
|
||||||
nonDuplicatedCookiesSet.addAll(cookies);
|
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>(nonDuplicatedCookiesSet);
|
||||||
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>();
|
|
||||||
nonDuplicatedCookiesList.addAll(nonDuplicatedCookiesSet);
|
|
||||||
|
|
||||||
sCookieStore.put(url.host(), nonDuplicatedCookiesList);
|
sCookieStore.put(url.host(), nonDuplicatedCookiesList);
|
||||||
}
|
}
|
||||||
@ -133,7 +123,7 @@ public class HttpClient {
|
|||||||
sOkHttpClient = clientBuilder.build();
|
sOkHttpClient = clientBuilder.build();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log_OC.e(TAG, "Could not setup SSL system.", e);
|
Timber.e(e, "Could not setup SSL system.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sOkHttpClient;
|
return sOkHttpClient;
|
||||||
@ -142,7 +132,7 @@ public class HttpClient {
|
|||||||
private static HttpInterceptor getOkHttpInterceptor() {
|
private static HttpInterceptor getOkHttpInterceptor() {
|
||||||
if (sOkHttpInterceptor == null) {
|
if (sOkHttpInterceptor == null) {
|
||||||
sOkHttpInterceptor = new HttpInterceptor();
|
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.PARAM_SINGLE_COOKIE_HEADER, "true");
|
||||||
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
|
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
|
||||||
}
|
}
|
||||||
@ -158,7 +148,7 @@ public class HttpClient {
|
|||||||
public static void addHeaderForAllRequests(String headerName, String headerValue) {
|
public static void addHeaderForAllRequests(String headerName, String headerValue) {
|
||||||
HttpInterceptor httpInterceptor = getOkHttpInterceptor();
|
HttpInterceptor httpInterceptor = getOkHttpInterceptor();
|
||||||
|
|
||||||
if(getOkHttpInterceptor() != null) {
|
if (getOkHttpInterceptor() != null) {
|
||||||
httpInterceptor.addRequestInterceptor(
|
httpInterceptor.addRequestInterceptor(
|
||||||
new RequestHeaderInterceptor(headerName, headerValue)
|
new RequestHeaderInterceptor(headerName, headerValue)
|
||||||
);
|
);
|
||||||
@ -177,22 +167,6 @@ public class HttpClient {
|
|||||||
sContext = context;
|
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) {
|
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
|
||||||
return sCookieStore.get(httpUrl.host());
|
return sCookieStore.get(httpUrl.host());
|
||||||
}
|
}
|
||||||
@ -200,4 +174,4 @@ public class HttpClient {
|
|||||||
public void clearCookies() {
|
public void clearCookies() {
|
||||||
sCookieStore.clear();
|
sCookieStore.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -78,14 +78,18 @@ public abstract class DavMethod extends HttpBaseMethod {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
} else if (mResponse != null) {
|
} else if (mResponse != null) {
|
||||||
ResponseBody responseBody = ResponseBody.create(
|
// The check below should be included in okhttp library, method ResponseBody.create(
|
||||||
mResponse.body().contentType(),
|
// TODO check most recent versions of okhttp to see if this is already fixed and try to update if so
|
||||||
httpException.getResponseBody()
|
if (mResponse.body().contentType() != null) {
|
||||||
);
|
ResponseBody responseBody = ResponseBody.create(
|
||||||
|
mResponse.body().contentType(),
|
||||||
|
httpException.getResponseBody()
|
||||||
|
);
|
||||||
|
|
||||||
mResponse = mResponse.newBuilder()
|
mResponse = mResponse.newBuilder()
|
||||||
.body(responseBody)
|
.body(responseBody)
|
||||||
.build();
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpException.getCode();
|
return httpException.getCode();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.network;
|
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.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
@ -43,11 +43,8 @@ import java.security.cert.X509Certificate;
|
|||||||
*/
|
*/
|
||||||
public class AdvancedX509TrustManager implements X509TrustManager {
|
public class AdvancedX509TrustManager implements X509TrustManager {
|
||||||
|
|
||||||
private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
|
|
||||||
|
|
||||||
private X509TrustManager mStandardTrustManager;
|
private X509TrustManager mStandardTrustManager;
|
||||||
private KeyStore mKnownServersKeyStore;
|
private KeyStore mKnownServersKeyStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for AdvancedX509TrustManager
|
* Constructor for AdvancedX509TrustManager
|
||||||
*
|
*
|
||||||
@ -136,7 +133,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
|
|||||||
try {
|
try {
|
||||||
return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
|
return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
|
||||||
} catch (KeyStoreException e) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,11 +24,9 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.network;
|
package com.owncloud.android.lib.common.network;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -43,9 +41,6 @@ import java.util.Iterator;
|
|||||||
*/
|
*/
|
||||||
public class ChunkFromFileRequestBody extends FileRequestBody {
|
public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||||
|
|
||||||
private static final String TAG = ChunkFromFileRequestBody.class.getSimpleName();
|
|
||||||
|
|
||||||
//private final File mFile;
|
|
||||||
private final FileChannel mChannel;
|
private final FileChannel mChannel;
|
||||||
private final long mChunkSize;
|
private final long mChunkSize;
|
||||||
private long mOffset;
|
private long mOffset;
|
||||||
@ -89,17 +84,17 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
|
|||||||
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
||||||
while (mChannel.position() < maxCount) {
|
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);
|
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.buffer().write(mBuffer.array(), 0, readCount);
|
||||||
|
|
||||||
sink.flush();
|
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();
|
mBuffer.clear();
|
||||||
if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
|
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) {
|
} catch (Exception exception) {
|
||||||
|
Timber.e(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;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,13 +24,12 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.network;
|
package com.owncloud.android.lib.common.network;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import okio.Okio;
|
import okio.Okio;
|
||||||
import okio.Source;
|
import okio.Source;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -45,11 +44,9 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
|
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
|
||||||
|
|
||||||
private static final String TAG = FileRequestBody.class.getSimpleName();
|
|
||||||
|
|
||||||
protected File mFile;
|
protected File mFile;
|
||||||
private MediaType mContentType;
|
private MediaType mContentType;
|
||||||
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
final Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||||
|
|
||||||
public FileRequestBody(File file, MediaType contentType) {
|
public FileRequestBody(File file, MediaType contentType) {
|
||||||
mFile = file;
|
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() +
|
Timber.d("File with name " + mFile.getName() + " and size " + mFile.length() + " written in request body");
|
||||||
" written in request body");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
Timber.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@ package com.owncloud.android.lib.common.network;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import timber.log.Timber;
|
||||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -42,25 +41,6 @@ import java.security.cert.CertificateException;
|
|||||||
|
|
||||||
public class NetworkUtils {
|
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_FILENAME = "knownServers.bks";
|
||||||
|
|
||||||
private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
|
private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
|
||||||
@ -88,7 +68,7 @@ public class NetworkUtils {
|
|||||||
//mKnownServersStore = KeyStore.getInstance("BKS");
|
//mKnownServersStore = KeyStore.getInstance("BKS");
|
||||||
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
|
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()) {
|
if (localTrustStoreFile.exists()) {
|
||||||
InputStream in = new FileInputStream(localTrustStoreFile);
|
InputStream in = new FileInputStream(localTrustStoreFile);
|
||||||
try {
|
try {
|
||||||
@ -109,22 +89,9 @@ public class NetworkUtils {
|
|||||||
|
|
||||||
KeyStore knownServers = getKnownServersStore(context);
|
KeyStore knownServers = getKnownServersStore(context);
|
||||||
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
|
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
|
||||||
FileOutputStream fos = null;
|
try (FileOutputStream fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE)) {
|
||||||
try {
|
|
||||||
fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
|
|
||||||
knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
|
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.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class WebdavUtils {
|
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0;
|
||||||
public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
|
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_PATH_4_0_AND_LATER;
|
||||||
"dd.MM.yyyy hh:mm");
|
|
||||||
|
|
||||||
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("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
|
||||||
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", 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),
|
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) {
|
public static Date parseResponseDate(String date) {
|
||||||
Date returnDate = null;
|
Date returnDate;
|
||||||
SimpleDateFormat format = null;
|
SimpleDateFormat format;
|
||||||
for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
|
for (SimpleDateFormat datetimeFormat : DATETIME_FORMATS) {
|
||||||
try {
|
try {
|
||||||
format = DATETIME_FORMATS[i];
|
format = datetimeFormat;
|
||||||
synchronized (format) {
|
synchronized (format) {
|
||||||
returnDate = format.parse(date);
|
returnDate = format.parse(date);
|
||||||
}
|
}
|
||||||
@ -82,23 +83,6 @@ public class WebdavUtils {
|
|||||||
return encodedPath;
|
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
|
* @param httpBaseMethod from which to get the etag
|
||||||
* @return etag from response
|
* @return etag from response
|
||||||
@ -120,4 +104,17 @@ public class WebdavUtils {
|
|||||||
}
|
}
|
||||||
return result;
|
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.OwnCloudAccount;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
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.accounts.AccountUtils;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public abstract class RemoteOperation<T> implements Runnable {
|
public abstract class RemoteOperation<T> implements Runnable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,7 +27,6 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
* OCS API header value
|
* OCS API header value
|
||||||
*/
|
*/
|
||||||
public static final String OCS_API_HEADER_VALUE = "true";
|
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
|
* 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
|
* Object to interact with the remote server
|
||||||
*/
|
*/
|
||||||
protected OwnCloudClient mClient = null;
|
private OwnCloudClient mClient = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to interact with the remote server
|
* 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
|
* 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
|
* Handler to the thread where mListener methods will be called
|
||||||
*/
|
*/
|
||||||
protected Handler mListenerHandler = null;
|
private Handler mListenerHandler = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously executes the remote operation
|
* Asynchronously executes the remote operation
|
||||||
@ -75,12 +75,10 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||||
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
|
||||||
("Trying to execute a remote operation with a NULL Account");
|
|
||||||
}
|
}
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
|
||||||
("Trying to execute a remote operation with a NULL Context");
|
|
||||||
}
|
}
|
||||||
// mAccount and mContext in the runnerThread to create below
|
// mAccount and mContext in the runnerThread to create below
|
||||||
mAccount = account;
|
mAccount = account;
|
||||||
@ -106,11 +104,9 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
* the listener objects must be called.
|
* the listener objects must be called.
|
||||||
* @return Thread were the remote operation is executed.
|
* @return Thread were the remote operation is executed.
|
||||||
*/
|
*/
|
||||||
public Thread execute(OwnCloudClient client,
|
public Thread execute(OwnCloudClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||||
("Trying to execute a remote operation with a NULL OwnCloudClient");
|
|
||||||
}
|
}
|
||||||
mClient = client;
|
mClient = client;
|
||||||
if (client.getAccount() != null) {
|
if (client.getAccount() != null) {
|
||||||
@ -120,8 +116,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
|
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
("Trying to execute a remote operation asynchronously " +
|
("Trying to execute a remote operation asynchronously without a listener to notify the result");
|
||||||
"without a listener to notiy the result");
|
|
||||||
}
|
}
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
|
|
||||||
@ -134,12 +129,12 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
return runnerThread;
|
return runnerThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void grantOwnCloudClient() throws
|
private void grantOwnCloudClient() throws
|
||||||
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
||||||
if (mClient == null) {
|
if (mClient == null) {
|
||||||
if (mAccount != null && mContext != null) {
|
if (mAccount != null && mContext != null) {
|
||||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
mClient = SingleSessionManager.getDefaultSingleton().
|
||||||
getClientFor(ocAccount, mContext);
|
getClientFor(ocAccount, mContext);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Trying to run a remote operation " +
|
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) {
|
public RemoteOperationResult<T> execute(Account account, Context context) {
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
|
||||||
"Account");
|
|
||||||
}
|
}
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
|
||||||
"Context");
|
|
||||||
}
|
}
|
||||||
mAccount = account;
|
mAccount = account;
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
@ -192,7 +185,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronously executes the remote operation
|
* Synchronously executes the remote operation
|
||||||
*
|
* <p>
|
||||||
* Do not call this method from the main thread.
|
* Do not call this method from the main thread.
|
||||||
*
|
*
|
||||||
* @param client Client object to reach an ownCloud server during the execution of
|
* @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) {
|
public RemoteOperationResult<T> execute(OwnCloudClient client) {
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||||
"OwnCloudClient");
|
|
||||||
}
|
}
|
||||||
mClient = client;
|
mClient = client;
|
||||||
if (client.getAccount() != null) {
|
if (client.getAccount() != null) {
|
||||||
@ -224,8 +216,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
*/
|
*/
|
||||||
public RemoteOperationResult<T> execute(OkHttpClient client, Context context) {
|
public RemoteOperationResult<T> execute(OkHttpClient client, Context context) {
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||||
"OwnCloudClient");
|
|
||||||
}
|
}
|
||||||
mHttpClient = client;
|
mHttpClient = client;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@ -236,9 +227,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* Run operation for asynchronous or synchronous 'onExecute' method.
|
* Run operation for asynchronous or synchronous 'onExecute' method.
|
||||||
* <p>
|
* <p>
|
||||||
* Considers and performs silent refresh of account credentials if possible, and if
|
* Considers and performs silent refresh of account credentials if possible
|
||||||
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
|
|
||||||
* parameter 'true' before the execution.
|
|
||||||
*
|
*
|
||||||
* @return Remote operation result
|
* @return Remote operation result
|
||||||
*/
|
*/
|
||||||
@ -251,7 +240,7 @@ public abstract class RemoteOperation<T> implements Runnable {
|
|||||||
result = run(mClient);
|
result = run(mClient);
|
||||||
|
|
||||||
} catch (AccountsException | IOException e) {
|
} 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);
|
result = new RemoteOperationResult<>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.HttpConstants;
|
||||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
@ -60,14 +60,13 @@ public class RemoteOperationResult<T>
|
|||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 4968939884332372230L;
|
private static final long serialVersionUID = 4968939884332372230L;
|
||||||
|
|
||||||
private static final String TAG = RemoteOperationResult.class.getSimpleName();
|
|
||||||
private boolean mSuccess = false;
|
private boolean mSuccess = false;
|
||||||
private int mHttpCode = -1;
|
private int mHttpCode = -1;
|
||||||
private String mHttpPhrase = null;
|
private String mHttpPhrase = null;
|
||||||
private Exception mException = null;
|
private Exception mException = null;
|
||||||
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
|
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
|
||||||
private String mRedirectedLocation;
|
private String mRedirectedLocation;
|
||||||
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
private List<String> mAuthenticate = new ArrayList<>();
|
||||||
private String mLastPermanentLocation = null;
|
private String mLastPermanentLocation = null;
|
||||||
private T mData = null;
|
private T mData = null;
|
||||||
|
|
||||||
@ -189,10 +188,14 @@ public class RemoteOperationResult<T>
|
|||||||
try {
|
try {
|
||||||
if (xmlParser.parseXMLResponse(is)) {
|
if (xmlParser.parseXMLResponse(is)) {
|
||||||
mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
|
mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
|
||||||
|
} else {
|
||||||
|
parseErrorMessageAndSetCode(
|
||||||
|
httpMethod.getResponseBodyAsString(),
|
||||||
|
ResultCode.SPECIFIC_BAD_REQUEST
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} 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)
|
// mCode stays as set in this(success, httpCode, headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +253,9 @@ public class RemoteOperationResult<T>
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ("www-authenticate".equals(header.getKey().toLowerCase())) {
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
||||||
Log_OC.d(TAG,
|
Timber.d("RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + mHttpCode + " " + mHttpPhrase);
|
||||||
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
|
||||||
|
|
||||||
mHttpCode + " " + mHttpPhrase
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,21 +309,19 @@ public class RemoteOperationResult<T>
|
|||||||
*
|
*
|
||||||
* @param bodyResponse okHttp response body
|
* @param bodyResponse okHttp response body
|
||||||
* @param resultCode our own custom result code
|
* @param resultCode our own custom result code
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
|
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
|
||||||
|
|
||||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||||
ErrorMessageParser xmlParser = new ErrorMessageParser();
|
ErrorMessageParser xmlParser = new ErrorMessageParser();
|
||||||
try {
|
try {
|
||||||
String errorMessage = xmlParser.parseXMLResponse(is);
|
String errorMessage = xmlParser.parseXMLResponse(is);
|
||||||
if (errorMessage != "" && errorMessage != null) {
|
if (!errorMessage.equals("")) {
|
||||||
mCode = resultCode;
|
mCode = resultCode;
|
||||||
mHttpPhrase = errorMessage;
|
mHttpPhrase = errorMessage;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} 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)
|
// mCode stays as set in this(success, httpCode, headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,7 +375,7 @@ public class RemoteOperationResult<T>
|
|||||||
previousCause = cause;
|
previousCause = cause;
|
||||||
cause = cause.getCause();
|
cause = cause.getCause();
|
||||||
}
|
}
|
||||||
if (cause != null && cause instanceof CertificateCombinedException) {
|
if (cause instanceof CertificateCombinedException) {
|
||||||
result = (CertificateCombinedException) cause;
|
result = (CertificateCombinedException) cause;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -497,7 +496,7 @@ public class RemoteOperationResult<T>
|
|||||||
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
|
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getAuthenticateHeaders() {
|
public List<String> getAuthenticateHeaders() {
|
||||||
return mAuthenticate;
|
return mAuthenticate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,6 +571,7 @@ public class RemoteOperationResult<T>
|
|||||||
SERVICE_UNAVAILABLE,
|
SERVICE_UNAVAILABLE,
|
||||||
SPECIFIC_SERVICE_UNAVAILABLE,
|
SPECIFIC_SERVICE_UNAVAILABLE,
|
||||||
SPECIFIC_UNSUPPORTED_MEDIA_TYPE,
|
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())
|
if (!directory.exists())
|
||||||
directory.mkdirs()
|
directory.mkdirs()
|
||||||
Timber.plant(FileLoggingTree(directory, filename = storagePath, delegator = Log_OC::class.java))
|
Timber.plant(FileLoggingTree(directory, filename = storagePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopLogging() {
|
fun stopLogging() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @author David González Verdugo
|
* @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
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2,
|
* 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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,8 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod;
|
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.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
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.net.URL;
|
||||||
import java.util.concurrent.TimeUnit;
|
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
|
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||||
* in the same account.
|
* in the same account.
|
||||||
* <p>
|
*
|
||||||
* Allows renaming the moving file/folder at the same time.
|
* Allows renaming the moving file/folder at the same time.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author Christian Schabesberger
|
* @author Christian Schabesberger
|
||||||
|
* @author David González V.
|
||||||
*/
|
*/
|
||||||
public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
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_READ_TIMEOUT = 600000;
|
||||||
private static final int COPY_CONNECTION_TIMEOUT = 5000;
|
private static final int COPY_CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
@ -81,14 +78,6 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult<String> run(OwnCloudClient client) {
|
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)) {
|
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||||
// nothing to do!
|
// nothing to do!
|
||||||
@ -100,7 +89,7 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// perform remote operation
|
/// perform remote operation
|
||||||
RemoteOperationResult<String> result;
|
RemoteOperationResult result;
|
||||||
try {
|
try {
|
||||||
CopyMethod copyMethod =
|
CopyMethod copyMethod =
|
||||||
new CopyMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mSrcRemotePath)),
|
new CopyMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||||
@ -128,13 +117,11 @@ public class CopyRemoteFileOperation extends RemoteOperation<String> {
|
|||||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Timber.i("Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Timber.e(e, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import timber.log.Timber;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -47,8 +46,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public class CreateRemoteFolderOperation extends RemoteOperation {
|
public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||||
|
|
||||||
private static final String TAG = CreateRemoteFolderOperation.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final int READ_TIMEOUT = 30000;
|
private static final int READ_TIMEOUT = 30000;
|
||||||
private static final int CONNECTION_TIMEOUT = 5000;
|
private static final int CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
@ -75,24 +72,14 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult result = createFolder(client);
|
||||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
if (!result.isSuccess() && mCreateFullPath &&
|
||||||
boolean versionWithForbiddenChars =
|
RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) {
|
||||||
(version != null && version.isVersionWithForbiddenCharacters());
|
result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
|
||||||
boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars);
|
if (result.isSuccess()) {
|
||||||
if (noInvalidChars) {
|
result = createFolder(client); // second (and last) try
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,12 +95,12 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
result = (status == HttpConstants.HTTP_CREATED)
|
result = (status == HttpConstants.HTTP_CREATED)
|
||||||
? new RemoteOperationResult<>(ResultCode.OK)
|
? new RemoteOperationResult<>(ResultCode.OK)
|
||||||
: new RemoteOperationResult<>(mkcol);
|
: new RemoteOperationResult<>(mkcol);
|
||||||
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
Timber.d("Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||||
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(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;
|
return result;
|
||||||
@ -123,4 +110,4 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath, mCreateFullPath);
|
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath, mCreateFullPath);
|
||||||
return operation.execute(client);
|
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.OperationCancelledException;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -53,7 +53,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
public class DownloadRemoteFileOperation extends RemoteOperation {
|
public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName();
|
|
||||||
private static final int FORBIDDEN_ERROR = 403;
|
private static final int FORBIDDEN_ERROR = 403;
|
||||||
private static final int SERVICE_UNAVAILABLE_ERROR = 503;
|
private static final int SERVICE_UNAVAILABLE_ERROR = 503;
|
||||||
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||||
@ -81,13 +80,11 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
try {
|
try {
|
||||||
tmpFile.getParentFile().mkdirs();
|
tmpFile.getParentFile().mkdirs();
|
||||||
result = downloadFile(client, tmpFile);
|
result = downloadFile(client, tmpFile);
|
||||||
Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
Timber.i("Download of " + mRemotePath + " to " + getTmpPath() + ": " + result.getLogMessage());
|
||||||
result.getLogMessage());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
Timber.e(e, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + result.getLogMessage());
|
||||||
result.getLogMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -149,7 +146,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
final Date d = WebdavUtils.parseResponseDate(modificationTime);
|
final Date d = WebdavUtils.parseResponseDate(modificationTime);
|
||||||
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
||||||
} else {
|
} 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);
|
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
||||||
@ -158,7 +155,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
mEtag = mEtag.replace("\"", "");
|
mEtag = mEtag.replace("\"", "");
|
||||||
|
|
||||||
if (mEtag.length() == 0) {
|
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 {
|
} 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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,17 +24,15 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
public static final String PATH_SEPARATOR = "/";
|
public static final String PATH_SEPARATOR = "/";
|
||||||
public static final String FINAL_CHUNKS_FILE = ".file";
|
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();
|
String parentPath = new File(remotePath).getParent();
|
||||||
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
|
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
|
||||||
return parentPath;
|
return parentPath;
|
||||||
@ -45,40 +43,13 @@ public class FileUtils {
|
|||||||
* : , " , | , ? , *
|
* : , " , | , ? , *
|
||||||
*
|
*
|
||||||
* @param fileName
|
* @param fileName
|
||||||
* @param versionSupportsForbiddenChars
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
|
public static boolean isValidName(String fileName) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
|
|
||||||
Log_OC.d(TAG, "fileName =======" + fileName);
|
Timber.d("fileName =======%s", fileName);
|
||||||
if ((versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
|
if (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("*"))) {
|
|
||||||
|
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,7 +25,6 @@
|
|||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
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.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
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.net.URL;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -50,8 +49,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public class MoveRemoteFileOperation extends RemoteOperation {
|
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_READ_TIMEOUT = 600000;
|
||||||
private static final int MOVE_CONNECTION_TIMEOUT = 5000;
|
private static final int MOVE_CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
@ -87,16 +84,6 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
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)) {
|
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||||
// nothing to do!
|
// nothing to do!
|
||||||
return new RemoteOperationResult<>(ResultCode.OK);
|
return new RemoteOperationResult<>(ResultCode.OK);
|
||||||
@ -143,13 +130,11 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Timber.i("Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Timber.e(e, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -158,4 +143,4 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
protected boolean isSuccess(int status) {
|
protected boolean isSuccess(int status) {
|
||||||
return status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT;
|
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.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.net.URL;
|
||||||
import java.util.concurrent.TimeUnit;
|
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> {
|
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_READ_TIMEOUT = 40000;
|
||||||
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
|
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
@ -100,9 +99,7 @@ public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
e.printStackTrace();
|
Timber.e(e, "Synchronizing file %s", mRemotePath);
|
||||||
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
|
|
||||||
result.getException());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.net.URL;
|
||||||
import java.util.ArrayList;
|
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>> {
|
public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteFile>> {
|
||||||
|
|
||||||
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
|
|
||||||
|
|
||||||
private String mRemotePath;
|
private String mRemotePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,14 +106,15 @@ public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteF
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
} finally {
|
} finally {
|
||||||
if (result.isSuccess()) {
|
if (result == null) {
|
||||||
Log_OC.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
Timber.e("Synchronized " + mRemotePath + ": result is null");
|
||||||
|
} else if (result.isSuccess()) {
|
||||||
|
Timber.i("Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||||
} else {
|
} else {
|
||||||
if (result.isException()) {
|
if (result.isException()) {
|
||||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(),
|
Timber.e(result.getException(), "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||||
result.getException());
|
|
||||||
} else {
|
} 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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
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.OCPermissions;
|
||||||
import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
|
import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
|
||||||
import at.bitfire.dav4android.property.owncloud.OCSize;
|
import at.bitfire.dav4android.property.owncloud.OCSize;
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
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
|
* 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) {
|
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();
|
final List<Property> properties = davResource.getProperties();
|
||||||
|
|
||||||
for (Property property : properties) {
|
for (Property property : properties) {
|
||||||
@ -167,21 +163,6 @@ public class RemoteFile implements Parcelable, Serializable {
|
|||||||
readFromParcel(source);
|
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
|
* Getters and Setters
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
*
|
* Copyright (C) 2020 ownCloud GmbH.
|
||||||
* @author David A. Velasco
|
|
||||||
* Copyright (C) 2017 ownCloud GmbH.
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,44 +21,29 @@
|
|||||||
* THE SOFTWARE.
|
* 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 {
|
class RemoteFileUtil {
|
||||||
|
companion object {
|
||||||
private String mClientId;
|
/**
|
||||||
|
* Retrieves a relative path from a remote file url
|
||||||
private String mClientSecret;
|
*
|
||||||
|
*
|
||||||
private String mRedirectUri;
|
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
|
||||||
|
*
|
||||||
public OAuth2ClientConfiguration(String clientId, String clientSecret, String redirectUri) {
|
* @param url remote file url
|
||||||
mClientId = (clientId == null) ? "" : clientId;
|
* @param userId file owner
|
||||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
* @return remote relative path of the file
|
||||||
mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
*/
|
||||||
}
|
fun getRemotePathFromUrl(url: HttpUrl, userId: String): String? {
|
||||||
|
val davFilesPath = OwnCloudClient.WEBDAV_FILES_PATH_4_0 + userId
|
||||||
public String getClientId() {
|
val absoluteDavPath = Uri.decode(url.encodedPath())
|
||||||
return mClientId;
|
val pathToOc = absoluteDavPath.split(davFilesPath)[0]
|
||||||
}
|
return absoluteDavPath.replace(pathToOc + davFilesPath, "")
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.net.URL;
|
||||||
|
|
||||||
@ -46,7 +46,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
|||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class RemoveRemoteFileOperation extends RemoteOperation {
|
public class RemoveRemoteFileOperation extends RemoteOperation {
|
||||||
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
|
|
||||||
private String mRemotePath;
|
private String mRemotePath;
|
||||||
|
|
||||||
protected boolean removeChunksFolder = false;
|
protected boolean removeChunksFolder = false;
|
||||||
@ -81,11 +80,11 @@ public class RemoveRemoteFileOperation extends RemoteOperation {
|
|||||||
new RemoteOperationResult<>(OK) :
|
new RemoteOperationResult<>(OK) :
|
||||||
new RemoteOperationResult<>(deleteMethod);
|
new RemoteOperationResult<>(deleteMethod);
|
||||||
|
|
||||||
Log_OC.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
Timber.i("Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
|
Timber.e(e, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import timber.log.Timber;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -46,8 +45,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public class RenameRemoteFileOperation extends RemoteOperation {
|
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_READ_TIMEOUT = 600000;
|
||||||
private static final int RENAME_CONNECTION_TIMEOUT = 5000;
|
private static final int RENAME_CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
@ -86,15 +83,6 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
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 {
|
try {
|
||||||
if (mNewName.equals(mOldName)) {
|
if (mNewName.equals(mOldName)) {
|
||||||
return new RemoteOperationResult<>(ResultCode.OK);
|
return new RemoteOperationResult<>(ResultCode.OK);
|
||||||
@ -117,16 +105,14 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
? new RemoteOperationResult<>(ResultCode.OK)
|
? new RemoteOperationResult<>(ResultCode.OK)
|
||||||
: new RemoteOperationResult<>(move);
|
: new RemoteOperationResult<>(move);
|
||||||
|
|
||||||
Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
|
Timber.i("Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage()
|
|
||||||
);
|
|
||||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||||
return result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
|
Timber.e(e,
|
||||||
((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ": " +
|
"Rename " + mOldRemotePath + " to " + ((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ":" +
|
||||||
result.getLogMessage(), e);
|
" " + result.getLogMessage());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,9 +123,9 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
* @return 'True' if the target path is already used by an existing file.
|
* @return 'True' if the target path is already used by an existing file.
|
||||||
*/
|
*/
|
||||||
private boolean targetPathIsUsed(OwnCloudClient client) {
|
private boolean targetPathIsUsed(OwnCloudClient client) {
|
||||||
ExistenceCheckRemoteOperation existenceCheckRemoteOperation =
|
CheckPathExistenceRemoteOperation checkPathExistenceRemoteOperation =
|
||||||
new ExistenceCheckRemoteOperation(mNewRemotePath, false, false);
|
new CheckPathExistenceRemoteOperation(mNewRemotePath, false);
|
||||||
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
|
RemoteOperationResult exists = checkPathExistenceRemoteOperation.execute(client);
|
||||||
return exists.isSuccess();
|
return exists.isSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.OperationCancelledException;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -54,7 +54,6 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
|
|||||||
|
|
||||||
public class UploadRemoteFileOperation extends RemoteOperation {
|
public class UploadRemoteFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
|
||||||
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||||
protected String mLocalPath;
|
protected String mLocalPath;
|
||||||
protected String mRemotePath;
|
protected String mRemotePath;
|
||||||
@ -62,7 +61,7 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
protected String mFileLastModifTimestamp;
|
protected String mFileLastModifTimestamp;
|
||||||
protected PutMethod mPutMethod = null;
|
protected PutMethod mPutMethod = null;
|
||||||
protected String mRequiredEtag = null;
|
protected String mRequiredEtag = null;
|
||||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||||
|
|
||||||
protected FileRequestBody mFileRequestBody = null;
|
protected FileRequestBody mFileRequestBody = null;
|
||||||
|
|
||||||
@ -96,27 +95,25 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
} else {
|
} else {
|
||||||
// perform the upload
|
// perform the upload
|
||||||
result = uploadFile(client);
|
result = uploadFile(client);
|
||||||
Log_OC.i(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
Timber.i("Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
if (mPutMethod != null && mPutMethod.isAborted()) {
|
if (mPutMethod != null && mPutMethod.isAborted()) {
|
||||||
result = new RemoteOperationResult<>(new OperationCancelledException());
|
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
Timber.e(result.getException(),
|
||||||
result.getLogMessage(), new OperationCancelledException());
|
"Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult<>(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
Timber.e(e, "Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage());
|
||||||
result.getLogMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RemoteOperationResult<? extends Object> uploadFile(OwnCloudClient client) throws Exception {
|
protected RemoteOperationResult<?> uploadFile(OwnCloudClient client) throws Exception {
|
||||||
|
|
||||||
File fileToUpload = new File(mLocalPath);
|
File fileToUpload = new File(mLocalPath);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.network.ChunkFromFileRequestBody;
|
||||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.FileUtils;
|
||||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
@ -53,7 +53,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
|||||||
|
|
||||||
public static final long CHUNK_SIZE = 1024000;
|
public static final long CHUNK_SIZE = 1024000;
|
||||||
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
||||||
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
|
||||||
|
|
||||||
private String mTransferId;
|
private String mTransferId;
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
|||||||
|
|
||||||
status = client.executeHttpMethod(mPutMethod);
|
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 +
|
", chunk index " + chunkIndex + ", count " + chunkCount +
|
||||||
", HTTP result status " + status);
|
", HTTP result status " + status);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
package com.owncloud.android.lib.resources.response
|
||||||
|
|
||||||
package com.owncloud.android.lib.common;
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
import android.accounts.AuthenticatorException;
|
// Response retrieved by OCS Rest API, used to obtain capabilities, shares and user info among others.
|
||||||
import android.accounts.OperationCanceledException;
|
// More info: https://doc.owncloud.com/server/developer_manual/core/apis/ocs-capabilities.html
|
||||||
import android.content.Context;
|
@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;
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class MetaData(
|
||||||
/**
|
val status: String,
|
||||||
* Manager to create and reuse OwnCloudClient instances to access remote OC servers.
|
val statuscode: Int,
|
||||||
*
|
val message: String?
|
||||||
* @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;
|
|
||||||
}
|
|
@ -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 masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.http.methods.nonwebdav.PostMethod
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
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 com.owncloud.android.lib.resources.shares.RemoteShare.Companion.INIT_EXPIRATION_DATE_IN_MILLIS
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
|
import timber.log.Timber
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
@ -150,7 +150,7 @@ class CreateRemoteShareOperation(
|
|||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Exception while Creating New Share", e)
|
Timber.e(e, "Exception while Creating New Share")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -159,8 +159,6 @@ class CreateRemoteShareOperation(
|
|||||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = CreateRemoteShareOperation::class.java.simpleName
|
|
||||||
|
|
||||||
private const val PARAM_NAME = "name"
|
private const val PARAM_NAME = "name"
|
||||||
private const val PARAM_PASSWORD = "password"
|
private const val PARAM_PASSWORD = "password"
|
||||||
private const val PARAM_EXPIRATION_DATE = "expireDate"
|
private const val PARAM_EXPIRATION_DATE = "expireDate"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
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.net.URL;
|
||||||
|
|
||||||
@ -46,8 +46,6 @@ import java.net.URL;
|
|||||||
|
|
||||||
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
|
||||||
|
|
||||||
private long mRemoteId;
|
private long mRemoteId;
|
||||||
|
|
||||||
public GetRemoteShareOperation(long remoteId) {
|
public GetRemoteShareOperation(long remoteId) {
|
||||||
@ -85,7 +83,7 @@ public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult>
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult<>(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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import timber.log.Timber
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
@ -95,13 +95,13 @@ class GetRemoteShareesOperation
|
|||||||
|
|
||||||
val getMethod = GetMethod(URL(uriBuilder.build().toString()))
|
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 status = client.executeHttpMethod(getMethod)
|
||||||
val response = getMethod.responseBodyAsString
|
val response = getMethod.responseBodyAsString
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
Log_OC.d(TAG, "Successful response: " + response!!)
|
Timber.d("Successful response: $response")
|
||||||
|
|
||||||
// Parse the response
|
// Parse the response
|
||||||
val respJSON = JSONObject(response)
|
val respJSON = JSONObject(response)
|
||||||
@ -128,65 +128,61 @@ class GetRemoteShareesOperation
|
|||||||
for (j in 0 until jsonResults[i].length()) {
|
for (j in 0 until jsonResults[i].length()) {
|
||||||
val jsonResult = jsonResults[i].getJSONObject(j)
|
val jsonResult = jsonResults[i].getJSONObject(j)
|
||||||
data.add(jsonResult)
|
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 = RemoteOperationResult(OK)
|
||||||
result.data = data
|
result.data = data
|
||||||
|
|
||||||
Log_OC.d(TAG, "*** Get Users or groups completed ")
|
Timber.d("*** Get Users or groups completed ")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = RemoteOperationResult(getMethod)
|
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) {
|
if (response != null) {
|
||||||
Log_OC.e(TAG, "*** status code: $status; response message: $response")
|
Timber.e("*** status code: $status; response message: $response")
|
||||||
} else {
|
} else {
|
||||||
Log_OC.e(TAG, "*** status code: $status")
|
Timber.e("*** status code: $status")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Exception while getting users/groups", e)
|
Timber.e(e, "Exception while getting users/groups")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSuccess(status: Int): Boolean {
|
private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK
|
||||||
return status == HttpConstants.HTTP_OK
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val TAG = GetRemoteShareesOperation::class.java.simpleName
|
|
||||||
|
|
||||||
// OCS Routes
|
// 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
|
// Arguments - names
|
||||||
private val PARAM_FORMAT = "format"
|
private const val PARAM_FORMAT = "format"
|
||||||
private val PARAM_ITEM_TYPE = "itemType"
|
private const val PARAM_ITEM_TYPE = "itemType"
|
||||||
private val PARAM_SEARCH = "search"
|
private const val PARAM_SEARCH = "search"
|
||||||
private val PARAM_PAGE = "page" // default = 1
|
private const val PARAM_PAGE = "page" // default = 1
|
||||||
private val PARAM_PER_PAGE = "perPage" // default = 200
|
private const val PARAM_PER_PAGE = "perPage" // default = 200
|
||||||
|
|
||||||
// Arguments - constant values
|
// Arguments - constant values
|
||||||
private val VALUE_FORMAT = "json"
|
private const val VALUE_FORMAT = "json"
|
||||||
private val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups
|
private const val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups
|
||||||
|
|
||||||
// JSON Node names
|
// JSON Node names
|
||||||
private val NODE_OCS = "ocs"
|
private const val NODE_OCS = "ocs"
|
||||||
private val NODE_DATA = "data"
|
private const val NODE_DATA = "data"
|
||||||
private val NODE_EXACT = "exact"
|
private const val NODE_EXACT = "exact"
|
||||||
private val NODE_USERS = "users"
|
private const val NODE_USERS = "users"
|
||||||
private val NODE_GROUPS = "groups"
|
private const val NODE_GROUPS = "groups"
|
||||||
private val NODE_REMOTES = "remotes"
|
private const val NODE_REMOTES = "remotes"
|
||||||
val NODE_VALUE = "value"
|
const val NODE_VALUE = "value"
|
||||||
val PROPERTY_LABEL = "label"
|
const val PROPERTY_LABEL = "label"
|
||||||
val PROPERTY_SHARE_TYPE = "shareType"
|
const val PROPERTY_SHARE_TYPE = "shareType"
|
||||||
val PROPERTY_SHARE_WITH = "shareWith"
|
const val PROPERTY_SHARE_WITH = "shareWith"
|
||||||
val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo"
|
const val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.http.methods.nonwebdav.GetMethod
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
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.net.URL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,14 +89,14 @@ class GetRemoteSharesForFileOperation(
|
|||||||
result = parser.parse(getMethod.responseBodyAsString)
|
result = parser.parse(getMethod.responseBodyAsString)
|
||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
Log_OC.d(TAG, "Got " + result.data.shares.size + " shares")
|
Timber.d("Got " + result.data.shares.size + " shares")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = RemoteOperationResult(getMethod)
|
result = RemoteOperationResult(getMethod)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Exception while getting shares", e)
|
Timber.e(e, "Exception while getting shares")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -105,11 +105,8 @@ class GetRemoteSharesForFileOperation(
|
|||||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val TAG = GetRemoteSharesForFileOperation::class.java.simpleName
|
|
||||||
|
|
||||||
private const val PARAM_PATH = "path"
|
private const val PARAM_PATH = "path"
|
||||||
private const val PARAM_RESHARES = "reshares"
|
private const val PARAM_RESHARES = "reshares"
|
||||||
private const val PARAM_SUBFILES = "subfiles"
|
private const val PARAM_SUBFILES = "subfiles"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -42,8 +42,8 @@ data class RemoteShare(
|
|||||||
var sharedWithAdditionalInfo: String = "",
|
var sharedWithAdditionalInfo: String = "",
|
||||||
var name: String = "",
|
var name: String = "",
|
||||||
var shareLink: String = "",
|
var shareLink: String = "",
|
||||||
var fileSource: Long = 0,
|
var fileSource: String = "0",
|
||||||
var itemSource: Long = 0,
|
var itemSource: String = "0",
|
||||||
var shareType: ShareType? = ShareType.UNKNOWN,
|
var shareType: ShareType? = ShareType.UNKNOWN,
|
||||||
var permissions: Int = DEFAULT_PERMISSION,
|
var permissions: Int = DEFAULT_PERMISSION,
|
||||||
var sharedDate: Long = INIT_SHARED_DATE,
|
var sharedDate: Long = INIT_SHARED_DATE,
|
||||||
@ -66,16 +66,14 @@ data class RemoteShare(
|
|||||||
const val MAXIMUM_PERMISSIONS_FOR_FOLDER = MAXIMUM_PERMISSIONS_FOR_FILE +
|
const val MAXIMUM_PERMISSIONS_FOR_FOLDER = MAXIMUM_PERMISSIONS_FOR_FILE +
|
||||||
CREATE_PERMISSION_FLAG +
|
CREATE_PERMISSION_FLAG +
|
||||||
DELETE_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 = READ_PERMISSION_FLAG +
|
||||||
const val FEDERATED_PERMISSIONS_FOR_FILE_AFTER_OC9 = READ_PERMISSION_FLAG +
|
|
||||||
UPDATE_PERMISSION_FLAG +
|
UPDATE_PERMISSION_FLAG +
|
||||||
SHARE_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 +
|
UPDATE_PERMISSION_FLAG +
|
||||||
CREATE_PERMISSION_FLAG +
|
CREATE_PERMISSION_FLAG +
|
||||||
DELETE_PERMISSION_FLAG
|
DELETE_PERMISSION_FLAG +
|
||||||
const val FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9 =
|
SHARE_PERMISSION_FLAG
|
||||||
FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 + SHARE_PERMISSION_FLAG
|
|
||||||
|
|
||||||
const val INIT_EXPIRATION_DATE_IN_MILLIS: Long = 0
|
const val INIT_EXPIRATION_DATE_IN_MILLIS: Long = 0
|
||||||
const val INIT_SHARED_DATE: Long = 0
|
const val INIT_SHARED_DATE: Long = 0
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.http.methods.nonwebdav.DeleteMethod
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
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.net.URL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +75,7 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
|
|||||||
)
|
)
|
||||||
result = parser.parse(deleteMethod.responseBodyAsString)
|
result = parser.parse(deleteMethod.responseBodyAsString)
|
||||||
|
|
||||||
Log_OC.d(TAG, "Unshare " + remoteShareId + ": " + result.logMessage)
|
Timber.d("Unshare " + remoteShareId + ": " + result.logMessage)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = RemoteOperationResult(deleteMethod)
|
result = RemoteOperationResult(deleteMethod)
|
||||||
@ -83,16 +83,11 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
|
|||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Unshare Link Exception " + result.logMessage, e)
|
Timber.e(e, "Unshare Link Exception " + result.logMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
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
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author Christian Schabesberger
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author David A. Velasco
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
* @author Christian Schabesberger
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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 android.net.Uri
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
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 com.owncloud.android.lib.resources.status.OwnCloudVersion
|
||||||
import org.xmlpull.v1.XmlPullParserException
|
import org.xmlpull.v1.XmlPullParserException
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
@ -53,7 +53,7 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
|||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
val byteArrayServerResponse = ByteArrayInputStream(serverResponse.toByteArray())
|
val byteArrayServerResponse = ByteArrayInputStream(serverResponse.toByteArray())
|
||||||
if (shareXmlParser == null) {
|
if (shareXmlParser == null) {
|
||||||
Log_OC.w(TAG, "No ShareXmlParser provided, creating new instance ")
|
Timber.w("No ShareXmlParser provided, creating new instance")
|
||||||
shareXmlParser = ShareXMLParser()
|
shareXmlParser = ShareXMLParser()
|
||||||
}
|
}
|
||||||
val shares = shareXmlParser?.parseXMLResponse(byteArrayServerResponse)
|
val shares = shareXmlParser?.parseXMLResponse(byteArrayServerResponse)
|
||||||
@ -72,10 +72,10 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (serverBaseUri != null) {
|
if (serverBaseUri != null) {
|
||||||
val sharingLinkPath = ShareUtils.getSharingLinkPath(ownCloudVersion)
|
val sharingLinkPath = ShareUtils.SHARING_LINK_PATH
|
||||||
share.shareLink = serverBaseUri.toString() + sharingLinkPath + share.token
|
share.shareLink = serverBaseUri.toString() + sharingLinkPath + share.token
|
||||||
} else {
|
} else {
|
||||||
Log_OC.e(TAG, "Couldn't build link for public share :(")
|
Timber.e("Couldn't build link for public share :(")
|
||||||
}
|
}
|
||||||
|
|
||||||
share
|
share
|
||||||
@ -87,7 +87,7 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
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!! -> {
|
shareXmlParser?.isWrongParameter!! -> {
|
||||||
@ -107,18 +107,14 @@ class ShareToRemoteOperationResultParser(private var shareXmlParser: ShareXMLPar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: XmlPullParserException) {
|
} 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)
|
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
||||||
|
|
||||||
} catch (e: IOException) {
|
} 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)
|
result = RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG = ShareToRemoteOperationResultParser::class.java.simpleName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,8 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.shares;
|
package com.owncloud.android.lib.resources.shares;
|
||||||
|
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains Constants for Share Operation
|
* 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";
|
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:
|
// 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 = "/index.php/s/";
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -110,12 +110,16 @@ class ShareXMLParser {
|
|||||||
}
|
}
|
||||||
val name = parser.name
|
val name = parser.name
|
||||||
// read NODE_META and NODE_DATA
|
// read NODE_META and NODE_DATA
|
||||||
if (name.equals(NODE_META, ignoreCase = true)) {
|
when {
|
||||||
readMeta(parser)
|
name.equals(NODE_META, ignoreCase = true) -> {
|
||||||
} else if (name.equals(NODE_DATA, ignoreCase = true)) {
|
readMeta(parser)
|
||||||
shares = readData(parser)
|
}
|
||||||
} else {
|
name.equals(NODE_DATA, ignoreCase = true) -> {
|
||||||
skip(parser)
|
shares = readData(parser)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
skip(parser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shares
|
return shares
|
||||||
@ -130,24 +134,25 @@ class ShareXMLParser {
|
|||||||
@Throws(XmlPullParserException::class, IOException::class)
|
@Throws(XmlPullParserException::class, IOException::class)
|
||||||
private fun readMeta(parser: XmlPullParser) {
|
private fun readMeta(parser: XmlPullParser) {
|
||||||
parser.require(XmlPullParser.START_TAG, ns, NODE_META)
|
parser.require(XmlPullParser.START_TAG, ns, NODE_META)
|
||||||
//Log_OC.d(TAG, "---- NODE META ---");
|
|
||||||
while (parser.next() != XmlPullParser.END_TAG) {
|
while (parser.next() != XmlPullParser.END_TAG) {
|
||||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val name = parser.name
|
val name = parser.name
|
||||||
|
|
||||||
if (name.equals(NODE_STATUS, ignoreCase = true)) {
|
when {
|
||||||
status = readNode(parser, NODE_STATUS)
|
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))
|
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)
|
name.equals(NODE_MESSAGE, ignoreCase = true) -> {
|
||||||
|
message = readNode(parser, NODE_MESSAGE)
|
||||||
} else {
|
}
|
||||||
skip(parser)
|
else -> {
|
||||||
|
skip(parser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,33 +170,34 @@ class ShareXMLParser {
|
|||||||
var share: RemoteShare? = null
|
var share: RemoteShare? = null
|
||||||
|
|
||||||
parser.require(XmlPullParser.START_TAG, ns, NODE_DATA)
|
parser.require(XmlPullParser.START_TAG, ns, NODE_DATA)
|
||||||
//Log_OC.d(TAG, "---- NODE DATA ---");
|
|
||||||
while (parser.next() != XmlPullParser.END_TAG) {
|
while (parser.next() != XmlPullParser.END_TAG) {
|
||||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val name = parser.name
|
val name = parser.name
|
||||||
if (name.equals(NODE_ELEMENT, ignoreCase = true)) {
|
when {
|
||||||
readElement(parser, shares)
|
name.equals(NODE_ELEMENT, ignoreCase = true) -> {
|
||||||
|
readElement(parser, shares)
|
||||||
} else if (name.equals(NODE_ID, ignoreCase = true)) {// Parse Create XML Response
|
}
|
||||||
share = RemoteShare()
|
name.equals(NODE_ID, ignoreCase = true) -> {// Parse Create XML Response
|
||||||
val value = readNode(parser, NODE_ID)
|
share = RemoteShare()
|
||||||
share.id = Integer.parseInt(value).toLong()
|
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
|
name.equals(NODE_URL, ignoreCase = true) -> {
|
||||||
// in previous versions, it's received in the result of POST requests, but not
|
// NOTE: this field is received in all the public shares from OC 9.0.0
|
||||||
// in GET requests
|
// in previous versions, it's received in the result of POST requests, but not
|
||||||
share!!.shareType = ShareType.PUBLIC_LINK
|
// in GET requests
|
||||||
val value = readNode(parser, NODE_URL)
|
share!!.shareType = ShareType.PUBLIC_LINK
|
||||||
share.shareLink = value
|
val value = readNode(parser, NODE_URL)
|
||||||
|
share.shareLink = value
|
||||||
} else if (name.equals(NODE_TOKEN, ignoreCase = true)) {
|
}
|
||||||
share!!.token = readNode(parser, NODE_TOKEN)
|
name.equals(NODE_TOKEN, ignoreCase = true) -> {
|
||||||
|
share!!.token = readNode(parser, NODE_TOKEN)
|
||||||
} else {
|
}
|
||||||
skip(parser)
|
else -> {
|
||||||
|
skip(parser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +223,6 @@ class ShareXMLParser {
|
|||||||
|
|
||||||
val remoteShare = RemoteShare()
|
val remoteShare = RemoteShare()
|
||||||
|
|
||||||
//Log_OC.d(TAG, "---- NODE ELEMENT ---");
|
|
||||||
while (parser.next() != XmlPullParser.END_TAG) {
|
while (parser.next() != XmlPullParser.END_TAG) {
|
||||||
if (parser.eventType != XmlPullParser.START_TAG) {
|
if (parser.eventType != XmlPullParser.START_TAG) {
|
||||||
continue
|
continue
|
||||||
@ -243,7 +248,7 @@ class ShareXMLParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name.equals(NODE_ITEM_SOURCE, ignoreCase = true) -> {
|
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) -> {
|
name.equals(NODE_PARENT, ignoreCase = true) -> {
|
||||||
@ -260,7 +265,7 @@ class ShareXMLParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name.equals(NODE_FILE_SOURCE, ignoreCase = true) -> {
|
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) -> {
|
name.equals(NODE_PATH, ignoreCase = true) -> {
|
||||||
@ -343,7 +348,6 @@ class ShareXMLParser {
|
|||||||
private fun readNode(parser: XmlPullParser, node: String): String {
|
private fun readNode(parser: XmlPullParser, node: String): String {
|
||||||
parser.require(XmlPullParser.START_TAG, ns, node)
|
parser.require(XmlPullParser.START_TAG, ns, node)
|
||||||
val value = readText(parser)
|
val value = readText(parser)
|
||||||
//Log_OC.d(TAG, "node= " + node + ", value= " + value);
|
|
||||||
parser.require(XmlPullParser.END_TAG, ns, node)
|
parser.require(XmlPullParser.END_TAG, ns, node)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@ -387,8 +391,6 @@ class ShareXMLParser {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
//private static final String TAG = ShareXMLParser.class.getSimpleName();
|
|
||||||
|
|
||||||
// No namespaces
|
// No namespaces
|
||||||
private val ns: String? = null
|
private val ns: String? = null
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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.http.methods.nonwebdav.PutMethod
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
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 com.owncloud.android.lib.resources.shares.RemoteShare.Companion.DEFAULT_PERMISSION
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
|
import timber.log.Timber
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
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
|
* 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.
|
* Empty string clears the current name.
|
||||||
* Null results in no update applied to the name.
|
* Null results in no update applied to the name.
|
||||||
*/
|
*/
|
||||||
@ -70,7 +69,6 @@ class UpdateRemoteShareOperation
|
|||||||
/**
|
/**
|
||||||
* Password to update in Share resource.
|
* Password to update in Share resource.
|
||||||
*
|
*
|
||||||
* @param password Password to set to the target share.
|
|
||||||
* Empty string clears the current password.
|
* Empty string clears the current password.
|
||||||
* Null results in no update applied to the password.
|
* Null results in no update applied to the password.
|
||||||
*/
|
*/
|
||||||
@ -79,7 +77,6 @@ class UpdateRemoteShareOperation
|
|||||||
/**
|
/**
|
||||||
* Expiration date to update in Share resource.
|
* 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.
|
* A negative value clears the current expiration date.
|
||||||
* Zero value (start-of-epoch) results in no update done on
|
* Zero value (start-of-epoch) results in no update done on
|
||||||
* the expiration date.
|
* the expiration date.
|
||||||
@ -89,7 +86,6 @@ class UpdateRemoteShareOperation
|
|||||||
/**
|
/**
|
||||||
* Permissions to update in Share resource.
|
* 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.
|
* Values <= 0 result in no update applied to the permissions.
|
||||||
*/
|
*/
|
||||||
var permissions: Int = DEFAULT_PERMISSION
|
var permissions: Int = DEFAULT_PERMISSION
|
||||||
@ -97,7 +93,6 @@ class UpdateRemoteShareOperation
|
|||||||
/**
|
/**
|
||||||
* Enable upload permissions to update in Share resource.
|
* 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.
|
* Null results in no update applied to the upload permission.
|
||||||
*/
|
*/
|
||||||
var publicUpload: Boolean? = null
|
var publicUpload: Boolean? = null
|
||||||
@ -181,7 +176,7 @@ class UpdateRemoteShareOperation
|
|||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Exception while Creating New Share", e)
|
Timber.e(e, "Exception while Creating New Share")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -190,7 +185,6 @@ class UpdateRemoteShareOperation
|
|||||||
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = GetRemoteShareOperation::class.java.simpleName
|
|
||||||
|
|
||||||
private const val PARAM_NAME = "name"
|
private const val PARAM_NAME = "name"
|
||||||
private const val PARAM_PASSWORD = "password"
|
private const val PARAM_PASSWORD = "password"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @author David González Verdugo
|
* @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
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2,
|
* 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/>.
|
* 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.common.operations.RemoteOperationResult
|
||||||
import com.owncloud.android.lib.resources.Service
|
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 {
|
interface ShareService : Service {
|
||||||
fun getShares(
|
fun getShares(
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @author David González Verdugo
|
* @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
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2,
|
* 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/>.
|
* 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.common.operations.RemoteOperationResult
|
||||||
import com.owncloud.android.lib.resources.Service
|
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 masensio
|
||||||
* @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
|
* @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
|
||||||
* @author David González Verdugo
|
* @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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,7 +26,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.owncloud.android.lib.resources.status
|
package com.owncloud.android.lib.resources.status
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient
|
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.RemoteOperation
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC
|
import com.owncloud.android.lib.resources.response.CapabilityResponse
|
||||||
import org.json.JSONObject
|
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 java.net.URL
|
||||||
import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBooleanType
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Capabilities from the server
|
* Get the Capabilities from the server
|
||||||
@ -45,228 +50,51 @@ import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBool
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
|
class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
|
||||||
|
|
||||||
override fun run(client: OwnCloudClient): RemoteOperationResult<RemoteCapability> {
|
override fun run(client: OwnCloudClient): RemoteOperationResult<RemoteCapability> {
|
||||||
var result: RemoteOperationResult<RemoteCapability>
|
var result: RemoteOperationResult<RemoteCapability>
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val requestUri = client.baseUri
|
val uriBuilder = client.baseUri.buildUpon().apply {
|
||||||
val uriBuilder = requestUri.buildUpon()
|
appendEncodedPath(OCS_ROUTE) // avoid starting "/" in this method
|
||||||
uriBuilder.appendEncodedPath(OCS_ROUTE) // avoid starting "/" in this method
|
appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||||
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
}
|
||||||
|
val getMethod = GetMethod(URL(uriBuilder.build().toString())).apply {
|
||||||
val getMethod = GetMethod(URL(uriBuilder.build().toString()))
|
addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||||
|
}
|
||||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
|
||||||
|
|
||||||
val status = client.executeHttpMethod(getMethod)
|
val status = client.executeHttpMethod(getMethod)
|
||||||
|
|
||||||
val response = getMethod.responseBodyAsString
|
val response = getMethod.responseBodyAsString
|
||||||
|
|
||||||
if (!isSuccess(status)) {
|
if (status == HttpConstants.HTTP_OK) {
|
||||||
result = RemoteOperationResult(getMethod)
|
Timber.d("Successful response $response")
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = 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 {
|
} else {
|
||||||
result = RemoteOperationResult(statuscode, message, null)
|
result = RemoteOperationResult(getMethod)
|
||||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ")
|
Timber.e("Failed response while getting capabilities from the server status code: $status; response message: $response")
|
||||||
Log_OC.e(TAG, "*** status: $statusProp; message: $message")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result = RemoteOperationResult(e)
|
result = RemoteOperationResult(e)
|
||||||
Log_OC.e(TAG, "Exception while getting capabilities", e)
|
Timber.e(e, "Exception while getting capabilities")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSuccess(status: Int): Boolean {
|
|
||||||
return status == HttpConstants.HTTP_OK
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val TAG = GetRemoteCapabilitiesOperation::class.java.simpleName
|
|
||||||
|
|
||||||
// OCS Routes
|
// OCS Routes
|
||||||
private const val OCS_ROUTE = "ocs/v2.php/cloud/capabilities"
|
private const val OCS_ROUTE = "ocs/v2.php/cloud/capabilities"
|
||||||
|
|
||||||
@ -275,58 +103,5 @@ class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
|
|||||||
|
|
||||||
// Arguments - constant values
|
// Arguments - constant values
|
||||||
private const val VALUE_FORMAT = "json"
|
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