1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-10 17:36:12 +00:00

Merge pull request #338 from owncloud/master

1.0.6 stable
This commit is contained in:
Abel García de Prada 2020-08-12 16:35:18 +02:00 committed by GitHub
commit 3ea269fd98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 1091 additions and 1512 deletions

View File

@ -44,11 +44,11 @@ ownCloud Android Library is available under MIT license. See the file LICENSE.md
#### Third party libraries #### Third party libraries
ownCloud Android Library uses OkHttp version 3.10, licensed under Apache License and version 2.0. Besides, it uses Dav4Android, licensed under Mozilla Public License, v. 2.0 ownCloud Android Library uses OkHttp version 4.6.0, licensed under Apache License and version 2.0. Besides, it uses Dav4Android, licensed under Mozilla Public License, v. 2.0
### Compatibility ### Compatibility
ownCloud Android Library is valid for Android systems from version Android 2.2 (android:minSdkVersion="8" android:targetSdkVersion="19"). ownCloud Android Library is valid for Android systems from version Android 5 (android:minSdkVersion="21" android:targetSdkVersion="29").
ownCloud Android library supports ownCloud server from version 4.5. ownCloud Android library supports ownCloud server from version 4.5.

View File

@ -9,7 +9,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:4.0.1'
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"
} }

View File

@ -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-6.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

View File

@ -4,9 +4,9 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-allopen' apply plugin: 'kotlin-allopen'
dependencies { dependencies {
api 'com.squareup.okhttp3:okhttp:3.12.0' api 'com.squareup.okhttp3:okhttp:4.6.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_2.1.5'
api 'com.github.hannesa2:Logcat:1.6.0' api 'com.github.hannesa2:Logcat:1.6.0'
api 'net.openid:appauth:0.7.1' api 'net.openid:appauth:0.7.1'
@ -23,14 +23,14 @@ allOpen {
} }
android { android {
compileSdkVersion 28 compileSdkVersion 29
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 29
versionCode = 10000500 versionCode = 10000600
versionName = "1.0.5" versionName = "1.0.6"
// This is pretty ugly but manifest placeholders don't seem to work very well when using different modules // 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 // See https://github.com/openid/AppAuth-Android/issues/325

View File

@ -29,7 +29,7 @@ import android.accounts.AccountManager;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import android.net.Uri; import android.net.Uri;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4jvm.exception.HttpException;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
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;
@ -89,11 +89,6 @@ public class OwnCloudClient extends HttpClient {
if (!(mCredentials instanceof OwnCloudAnonymousCredentials)) { if (!(mCredentials instanceof OwnCloudAnonymousCredentials)) {
mCredentials = OwnCloudCredentialsFactory.getAnonymousCredentials(); mCredentials = OwnCloudCredentialsFactory.getAnonymousCredentials();
} }
mCredentials.applyTo(this);
}
void applyCredentials() {
mCredentials.applyTo(this);
} }
public int executeHttpMethod(HttpBaseMethod method) throws Exception { public int executeHttpMethod(HttpBaseMethod method) throws Exception {
@ -102,8 +97,17 @@ public class OwnCloudClient extends HttpClient {
int status; int status;
do { do {
setRequestId(method); String requestId = RandomUtils.generateRandomUUID();
// Header to allow tracing requests in apache and ownCloud logs
Timber.d("Executing in request with id %s", requestId);
method.setRequestHeader(HttpConstants.OC_X_REQUEST_ID, requestId);
method.setRequestHeader(HttpConstants.USER_AGENT_HEADER, SingleSessionManager.getUserAgent());
method.setRequestHeader(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
method.setRequestHeader(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
if (mCredentials.getHeaderAuth() != null) {
method.setRequestHeader(HttpConstants.AUTHORIZATION_HEADER, mCredentials.getHeaderAuth());
}
status = method.execute(); status = method.execute();
if (mFollowRedirects) { if (mFollowRedirects) {
@ -125,8 +129,17 @@ public class OwnCloudClient extends HttpClient {
int status; int status;
do { do {
setRequestId(method); String requestId = RandomUtils.generateRandomUUID();
// Header to allow tracing requests in apache and ownCloud logs
Timber.d("Executing in request with id %s", requestId);
method.setRequestHeader(OC_X_REQUEST_ID, requestId);
method.setRequestHeader(HttpConstants.USER_AGENT_HEADER, SingleSessionManager.getUserAgent());
method.setRequestHeader(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
method.setRequestHeader(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
if (mCredentials.getHeaderAuth() != null) {
method.setRequestHeader(HttpConstants.AUTHORIZATION_HEADER, mCredentials.getHeaderAuth());
}
status = method.execute(); status = method.execute();
repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter); repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter);
@ -138,19 +151,6 @@ public class OwnCloudClient extends HttpClient {
return status; return status;
} }
private void setRequestId(HttpBaseMethod method) {
// Clean previous request id. This is a bit hacky but is the only way to add request headers in WebDAV
// methods by using Dav4Android
deleteHeaderForAllRequests(OC_X_REQUEST_ID);
String requestId = RandomUtils.generateRandomUUID();
// Header to allow tracing requests in apache and ownCloud logs
addHeaderForAllRequests(OC_X_REQUEST_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 {
int redirectionsCount = 0; int redirectionsCount = 0;
int status = method.getStatusCode(); int status = method.getStatusCode();
@ -215,9 +215,6 @@ public class OwnCloudClient extends HttpClient {
public void exhaustResponse(InputStream responseBodyAsStream) { public void exhaustResponse(InputStream responseBodyAsStream) {
if (responseBodyAsStream != null) { if (responseBodyAsStream != null) {
try { try {
while (responseBodyAsStream.read(sExhaustBuffer) >= 0) {
;
}
responseBodyAsStream.close(); responseBodyAsStream.close();
} catch (IOException io) { } catch (IOException io) {
@ -273,7 +270,6 @@ public class OwnCloudClient extends HttpClient {
public void setCredentials(OwnCloudCredentials credentials) { public void setCredentials(OwnCloudCredentials credentials) {
if (credentials != null) { if (credentials != null) {
mCredentials = credentials; mCredentials = credentials;
mCredentials.applyTo(this);
} else { } else {
clearCredentials(); clearCredentials();
} }

View File

@ -32,6 +32,7 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.http.HttpClient; import com.owncloud.android.lib.common.http.HttpClient;
import timber.log.Timber; import timber.log.Timber;
@ -129,7 +130,6 @@ public class SingleSessionManager {
Timber.v("reusing client for session %s", sessionName); Timber.v("reusing client for session %s", sessionName);
} }
keepCredentialsUpdated(client);
keepCookiesUpdated(context, account, client); keepCookiesUpdated(context, account, client);
keepUriUpdated(account, client); keepUriUpdated(account, client);
} }
@ -176,10 +176,6 @@ public class SingleSessionManager {
Timber.d("All sessions saved"); Timber.d("All sessions saved");
} }
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
reusedClient.applyCredentials();
}
private void keepCookiesUpdated(Context context, OwnCloudAccount account, OwnCloudClient reusedClient) { private void keepCookiesUpdated(Context context, OwnCloudAccount account, OwnCloudClient reusedClient) {
AccountManager am = AccountManager.get(context.getApplicationContext()); AccountManager am = AccountManager.get(context.getApplicationContext());
if (am != null && account.getSavedAccount() != null) { if (am != null && account.getSavedAccount() != null) {
@ -191,6 +187,15 @@ public class SingleSessionManager {
} }
} }
public void refreshCredentialsForAccount(String accountName, OwnCloudCredentials credentials) {
OwnCloudClient ownCloudClient = mClientsWithKnownUsername.get(accountName);
if (ownCloudClient == null) {
return;
}
ownCloudClient.setCredentials(credentials);
mClientsWithKnownUsername.replace(accountName, ownCloudClient);
}
// this method is just a patch; we need to distinguish accounts in the same host but // this method is just a patch; we need to distinguish accounts in the same host but
// different paths; but that requires updating the accountNames for apps upgrading // different paths; but that requires updating the accountNames for apps upgrading
private void keepUriUpdated(OwnCloudAccount account, OwnCloudClient reusedClient) { private void keepUriUpdated(OwnCloudAccount account, OwnCloudClient reusedClient) {

View File

@ -41,6 +41,7 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import okhttp3.Cookie; import okhttp3.Cookie;
import timber.log.Timber; import timber.log.Timber;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -249,7 +250,7 @@ public class AccountUtils {
.domain(serverUri.getHost()) .domain(serverUri.getHost())
.path( .path(
serverUri.getPath().equals("") serverUri.getPath().equals("")
? FileUtils.PATH_SEPARATOR ? File.separator
: serverUri.getPath() : serverUri.getPath()
) )
.build()); .build());

View File

@ -23,11 +23,9 @@
*/ */
package com.owncloud.android.lib.common.authentication; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpClient;
import com.owncloud.android.lib.common.http.HttpConstants;
import okhttp3.Credentials; import okhttp3.Credentials;
import okhttp3.internal.Util;
import static java.nio.charset.StandardCharsets.UTF_8;
public class OwnCloudBasicCredentials implements OwnCloudCredentials { public class OwnCloudBasicCredentials implements OwnCloudCredentials {
@ -39,21 +37,6 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
mPassword = password != null ? password : ""; mPassword = password != null ? password : "";
} }
public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) {
mUsername = username != null ? username : "";
mPassword = password != null ? password : "";
}
@Override
public void applyTo(OwnCloudClient client) {
// Clear previous basic credentials
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
HttpClient.addHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER,
Credentials.basic(mUsername, mPassword, Util.UTF_8));
}
@Override @Override
public String getUsername() { public String getUsername() {
return mUsername; return mUsername;
@ -64,6 +47,11 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
return mPassword; return mPassword;
} }
@Override
public String getHeaderAuth() {
return Credentials.basic(mUsername, mPassword, UTF_8);
}
@Override @Override
public boolean authTokenExpires() { public boolean authTokenExpires() {
return false; return false;

View File

@ -23,8 +23,6 @@
*/ */
package com.owncloud.android.lib.common.authentication; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
public class OwnCloudBearerCredentials implements OwnCloudCredentials { public class OwnCloudBearerCredentials implements OwnCloudCredentials {
@ -37,16 +35,6 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials {
mAccessToken = accessToken != null ? accessToken : ""; mAccessToken = accessToken != null ? accessToken : "";
} }
@Override
public void applyTo(OwnCloudClient client) {
// Clear previous credentials
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
HttpClient.addHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER,
HttpConstants.BEARER_AUTHORIZATION_KEY + mAccessToken);
}
@Override @Override
public String getUsername() { public String getUsername() {
// not relevant for authentication, but relevant for informational purposes // not relevant for authentication, but relevant for informational purposes
@ -58,6 +46,11 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials {
return mAccessToken; return mAccessToken;
} }
@Override
public String getHeaderAuth() {
return HttpConstants.BEARER_AUTHORIZATION_KEY + mAccessToken;
}
@Override @Override
public boolean authTokenExpires() { public boolean authTokenExpires() {
return true; return true;

View File

@ -24,16 +24,14 @@
package com.owncloud.android.lib.common.authentication; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
public interface OwnCloudCredentials { public interface OwnCloudCredentials {
void applyTo(OwnCloudClient ownCloudClient);
String getUsername(); String getUsername();
String getAuthToken(); String getAuthToken();
String getHeaderAuth();
boolean authTokenExpires(); boolean authTokenExpires();
boolean authTokenCanBeRefreshed(); boolean authTokenCanBeRefreshed();

View File

@ -55,14 +55,12 @@ public class OwnCloudCredentialsFactory {
} }
@Override @Override
public void applyTo(OwnCloudClient client) { public String getAuthToken() {
// Clear previous basic credentials return "";
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
} }
@Override @Override
public String getAuthToken() { public String getHeaderAuth() {
return ""; return "";
} }

View File

@ -26,9 +26,6 @@ package com.owncloud.android.lib.common.http;
import android.content.Context; import android.content.Context;
import com.owncloud.android.lib.common.SingleSessionManager;
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import okhttp3.Cookie; import okhttp3.Cookie;
@ -58,7 +55,6 @@ import java.util.concurrent.TimeUnit;
*/ */
public class HttpClient { public class HttpClient {
private static OkHttpClient sOkHttpClient; private static OkHttpClient sOkHttpClient;
private static HttpInterceptor sOkHttpInterceptor;
private static Context sContext; private static Context sContext;
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>(); private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
@ -71,6 +67,10 @@ public class HttpClient {
SSLContext sslContext; SSLContext sslContext;
try { try {
sslContext = SSLContext.getInstance("TLSv1.3");
} catch (NoSuchAlgorithmException tlsv13Exception) {
try {
Timber.w("TLSv1.3 is not supported in this device; falling through TLSv1.2");
sslContext = SSLContext.getInstance("TLSv1.2"); sslContext = SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException tlsv12Exception) { } catch (NoSuchAlgorithmException tlsv12Exception) {
try { try {
@ -83,6 +83,7 @@ public class HttpClient {
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html // http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
} }
} }
}
sslContext.init(null, new TrustManager[]{trustManager}, null); sslContext.init(null, new TrustManager[]{trustManager}, null);
@ -109,7 +110,6 @@ public class HttpClient {
}; };
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(getOkHttpInterceptor())
.protocols(Arrays.asList(Protocol.HTTP_1_1)) .protocols(Arrays.asList(Protocol.HTTP_1_1))
.readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
@ -129,36 +129,6 @@ public class HttpClient {
return sOkHttpClient; return sOkHttpClient;
} }
private static HttpInterceptor getOkHttpInterceptor() {
if (sOkHttpInterceptor == null) {
sOkHttpInterceptor = new HttpInterceptor();
addHeaderForAllRequests(HttpConstants.USER_AGENT_HEADER, SingleSessionManager.getUserAgent());
addHeaderForAllRequests(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
}
return sOkHttpInterceptor;
}
/**
* Add header that will be included for all the requests from now on
*
* @param headerName
* @param headerValue
*/
public static void addHeaderForAllRequests(String headerName, String headerValue) {
HttpInterceptor httpInterceptor = getOkHttpInterceptor();
if (getOkHttpInterceptor() != null) {
httpInterceptor.addRequestInterceptor(
new RequestHeaderInterceptor(headerName, headerValue)
);
}
}
public static void deleteHeaderForAllRequests(String headerName) {
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
}
public Context getContext() { public Context getContext() {
return sContext; return sContext;
} }

View File

@ -74,8 +74,8 @@ public class TLSSocketFactory extends SSLSocketFactory {
} }
private Socket enableTLSOnSocket(Socket socket) { private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) { if((socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2", "TLSv1.3"});
} }
return socket; return socket;
} }

View File

@ -1,116 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.interceptors;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.ListIterator;
/**
* Http interceptor to use multiple interceptors in the same {@link okhttp3.OkHttpClient} instance
*
* @author David González Verdugo
*/
public class HttpInterceptor implements Interceptor {
private final ArrayList<RequestInterceptor> mRequestInterceptors = new ArrayList<>();
private final ArrayList<ResponseInterceptor> mResponseInterceptors = new ArrayList<>();
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
ListIterator<RequestInterceptor> requestInterceptorIterator = mRequestInterceptors.listIterator();
while (requestInterceptorIterator.hasNext()) {
RequestInterceptor currentRequestInterceptor = requestInterceptorIterator.next();
request = currentRequestInterceptor.intercept(request);
}
Response response = chain.proceed(request);
ListIterator<ResponseInterceptor> responseInterceptorIterator = mResponseInterceptors.listIterator();
while (responseInterceptorIterator.hasNext()) {
ResponseInterceptor currentResponseInterceptor = responseInterceptorIterator.next();
response = currentResponseInterceptor.intercept(response);
}
return response;
}
public HttpInterceptor addRequestInterceptor(RequestInterceptor requestInterceptor) {
mRequestInterceptors.listIterator().add(requestInterceptor);
return this;
}
public HttpInterceptor addResponseInterceptor(ResponseInterceptor responseInterceptor) {
mResponseInterceptors.listIterator().add(responseInterceptor);
return this;
}
public ArrayList<RequestInterceptor> getRequestInterceptors() {
return mRequestInterceptors;
}
private ArrayList<RequestHeaderInterceptor> getRequestHeaderInterceptors() {
ArrayList<RequestHeaderInterceptor> requestHeaderInterceptors = new ArrayList<>();
for (RequestInterceptor requestInterceptor : mRequestInterceptors) {
if (requestInterceptor instanceof RequestHeaderInterceptor) {
requestHeaderInterceptors.add((RequestHeaderInterceptor) requestInterceptor);
}
}
return requestHeaderInterceptors;
}
public void deleteRequestHeaderInterceptor(String headerName) {
ListIterator<RequestInterceptor> requestInterceptorIterator = mRequestInterceptors.listIterator();
while (requestInterceptorIterator.hasNext()) {
RequestInterceptor currentRequestInterceptor = requestInterceptorIterator.next();
if (currentRequestInterceptor instanceof RequestHeaderInterceptor &&
((RequestHeaderInterceptor) currentRequestInterceptor).getHeaderName().equals(headerName)) {
requestInterceptorIterator.remove();
}
}
}
public ArrayList<ResponseInterceptor> getResponseInterceptors() {
return mResponseInterceptors;
}
public interface RequestInterceptor {
Request intercept(Request request) throws IOException;
}
public interface ResponseInterceptor {
Response intercept(Response response) throws IOException;
}
}

View File

@ -1,54 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.interceptors;
import okhttp3.Request;
/**
* Intercept requests to update their headers
*/
public class RequestHeaderInterceptor implements HttpInterceptor.RequestInterceptor {
private String mHeaderName;
private String mHeaderValue;
public RequestHeaderInterceptor(String headerName, String headerValue) {
this.mHeaderName = headerName;
this.mHeaderValue = headerValue;
}
@Override
public Request intercept(Request request) {
return request.newBuilder().addHeader(mHeaderName, mHeaderValue).build();
}
public String getHeaderName() {
return mHeaderName;
}
public String getHeaderValue() {
return mHeaderValue;
}
}

View File

@ -1,191 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods;
import com.owncloud.android.lib.common.http.HttpClient;
import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Wrapper to perform http calls transparently by using:
* - OkHttp for non webdav methods
* - Dav4Android for webdav methods
*
* @author David González Verdugo
*/
public abstract class HttpBaseMethod {
protected OkHttpClient mOkHttpClient;
protected Request mRequest;
protected RequestBody mRequestBody;
protected Response mResponse;
protected String mResponseBodyString;
protected Call mCall;
protected HttpBaseMethod(URL url) {
mOkHttpClient = HttpClient.getOkHttpClient();
mRequest = new Request.Builder()
.url(HttpUrl.parse(url.toString()))
.build();
}
public int execute() throws Exception {
return onExecute();
}
public void abort() {
mCall.cancel();
}
public boolean isAborted() {
return mCall.isCanceled();
}
//////////////////////////////
// For override
//////////////////////////////
protected abstract int onExecute() throws Exception;
//////////////////////////////
// Getter
//////////////////////////////
// Request
public Headers getRequestHeaders() {
return mRequest.headers();
}
public String getRequestHeader(String name) {
return mRequest.header(name);
}
// Response
public int getStatusCode() {
return mResponse.code();
}
public String getStatusMessage() {
return mResponse.message();
}
public String getResponseBodyAsString() throws IOException {
if (mResponseBodyString == null && mResponse.body() != null) {
mResponseBodyString = mResponse.body().string();
}
return mResponseBodyString;
}
public InputStream getResponseBodyAsStream() {
if (mResponse.body() != null) {
return mResponse.body().byteStream();
}
return null;
}
public Headers getResponseHeaders() {
return mResponse.headers();
}
public String getResponseHeader(String headerName) {
return mResponse.header(headerName);
}
public boolean getRetryOnConnectionFailure() {
return mOkHttpClient.retryOnConnectionFailure();
}
//////////////////////////////
// Setter
//////////////////////////////
// Connection parameters
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
mOkHttpClient = mOkHttpClient.newBuilder()
.retryOnConnectionFailure(retryOnConnectionFailure)
.build();
}
public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
mOkHttpClient = mOkHttpClient.newBuilder()
.readTimeout(readTimeout, timeUnit)
.build();
}
public void setConnectionTimeout(long connectionTimeout, TimeUnit timeUnit) {
mOkHttpClient = mOkHttpClient.newBuilder()
.readTimeout(connectionTimeout, timeUnit)
.build();
}
public void setFollowRedirects(boolean followRedirects) {
mOkHttpClient = mOkHttpClient.newBuilder()
.followRedirects(followRedirects)
.build();
}
// Request
public void addRequestHeader(String name, String value) {
mRequest = mRequest.newBuilder()
.addHeader(name, value)
.build();
}
/**
* Sets a header and replace it if already exists with that name
*
* @param name header name
* @param value header value
*/
public void setRequestHeader(String name, String value) {
mRequest = mRequest.newBuilder()
.header(name, value)
.build();
}
public void setRequestBody(RequestBody requestBody) {
mRequestBody = requestBody;
}
public void setUrl(HttpUrl url) {
mRequest = mRequest.newBuilder()
.url(url)
.build();
}
}

View File

@ -0,0 +1,152 @@
package com.owncloud.android.lib.common.http.methods
import com.owncloud.android.lib.common.http.HttpClient
import okhttp3.Call
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.InputStream
import java.net.MalformedURLException
import java.net.URL
import java.util.concurrent.TimeUnit
abstract class HttpBaseMethod constructor(url: URL) {
var okHttpClient: OkHttpClient
var httpUrl: HttpUrl = url.toHttpUrlOrNull() ?: throw MalformedURLException()
var request: Request
abstract var response: Response
var call: Call? = null
init {
okHttpClient = HttpClient.getOkHttpClient()
request = Request.Builder()
.url(httpUrl)
.build()
}
@Throws(Exception::class)
open fun execute(): Int {
return onExecute()
}
open fun setUrl(url: HttpUrl) {
request = request.newBuilder()
.url(url)
.build()
}
/****************
*** Requests ***
****************/
fun getRequestHeader(name: String): String? {
return request.header(name)
}
fun getRequestHeadersAsHashMap(): HashMap<String, String?> {
val headers: HashMap<String, String?> = HashMap()
val superHeaders: Set<String> = request.headers.names()
superHeaders.forEach {
headers[it] = getRequestHeader(it)
}
return headers
}
open fun addRequestHeader(name: String, value: String) {
request = request.newBuilder()
.addHeader(name, value)
.build()
}
/**
* Sets a header and replace it if already exists with that name
*
* @param name header name
* @param value header value
*/
open fun setRequestHeader(name: String, value: String) {
request = request.newBuilder()
.header(name, value)
.build()
}
/****************
*** Response ***
****************/
val statusCode: Int
get() = response.code
val statusMessage: String
get() = response.message
// Headers
open fun getResponseHeaders(): Headers? {
return response.headers
}
open fun getResponseHeader(headerName: String): String? {
return response.header(headerName)
}
// Body
fun getResponseBodyAsString(): String? = response.body?.string()
open fun getResponseBodyAsStream(): InputStream? {
return response.body?.byteStream()
}
/*************************
*** Connection Params ***
*************************/
//////////////////////////////
// Setter
//////////////////////////////
// Connection parameters
open fun setRetryOnConnectionFailure(retryOnConnectionFailure: Boolean) {
okHttpClient = okHttpClient.newBuilder()
.retryOnConnectionFailure(retryOnConnectionFailure)
.build()
}
open fun setReadTimeout(readTimeout: Long, timeUnit: TimeUnit) {
okHttpClient = okHttpClient.newBuilder()
.readTimeout(readTimeout, timeUnit)
.build()
}
open fun setConnectionTimeout(
connectionTimeout: Long,
timeUnit: TimeUnit
) {
okHttpClient = okHttpClient.newBuilder()
.readTimeout(connectionTimeout, timeUnit)
.build()
}
open fun setFollowRedirects(followRedirects: Boolean) {
okHttpClient = okHttpClient.newBuilder()
.followRedirects(followRedirects)
.build()
}
/************
*** Call ***
************/
open fun abort() {
call?.cancel()
}
open val isAborted: Boolean
get() = call?.isCanceled() ?: false
//////////////////////////////
// For override
//////////////////////////////
@Throws(Exception::class)
protected abstract fun onExecute(): Int
}

View File

@ -21,29 +21,22 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.nonwebdav
package com.owncloud.android.lib.common.http.methods.nonwebdav; import java.io.IOException
import java.net.URL
import java.io.IOException;
import java.net.URL;
/** /**
* OkHttp delete calls wrapper * OkHttp delete calls wrapper
* *
* @author David González Verdugo * @author David González Verdugo
*/ */
public class DeleteMethod extends HttpMethod { class DeleteMethod(url: URL) : HttpMethod(url) {
@Throws(IOException::class)
public DeleteMethod(URL url) { override fun onExecute(): Int {
super(url); request = request.newBuilder()
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.delete() .delete()
.build(); .build()
return super.onExecute()
return super.onExecute();
} }
} }

View File

@ -21,29 +21,22 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.nonwebdav
package com.owncloud.android.lib.common.http.methods.nonwebdav; import java.io.IOException
import java.net.URL
import java.io.IOException;
import java.net.URL;
/** /**
* OkHttp get calls wrapper * OkHttp get calls wrapper
* *
* @author David González Verdugo * @author David González Verdugo
*/ */
public class GetMethod extends HttpMethod { class GetMethod(url: URL) : HttpMethod(url) {
@Throws(IOException::class)
public GetMethod(URL url) { override fun onExecute(): Int {
super(url); request = request.newBuilder()
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.get() .get()
.build(); .build()
return super.onExecute()
return super.onExecute();
} }
} }

View File

@ -21,29 +21,26 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.nonwebdav
package com.owncloud.android.lib.common.http.methods.nonwebdav; import com.owncloud.android.lib.common.http.methods.HttpBaseMethod
import okhttp3.Response
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod; import java.net.URL
import java.io.IOException;
import java.net.URL;
/** /**
* Wrapper to perform OkHttp calls * Wrapper to perform OkHttp calls
* *
* @author David González Verdugo * @author David González Verdugo
*/ */
public abstract class HttpMethod extends HttpBaseMethod { abstract class HttpMethod(
url: URL
) : HttpBaseMethod(url) {
public HttpMethod(URL url) { override lateinit var response: Response
super(url);
}
@Override public override fun onExecute(): Int {
public int onExecute() throws IOException { call = okHttpClient.newCall(request)
mCall = mOkHttpClient.newCall(mRequest); call?.let { response = it.execute() }
mResponse = mCall.execute(); return super.statusCode
return super.getStatusCode();
} }
} }

View File

@ -21,29 +21,26 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.nonwebdav
package com.owncloud.android.lib.common.http.methods.nonwebdav; import okhttp3.RequestBody
import java.io.IOException
import java.io.IOException; import java.net.URL
import java.net.URL;
/** /**
* OkHttp post calls wrapper * OkHttp post calls wrapper
* *
* @author David González Verdugo * @author David González Verdugo
*/ */
public class PostMethod extends HttpMethod { class PostMethod(
url: URL,
public PostMethod(URL url) { private val postRequestBody: RequestBody
super(url); ) : HttpMethod(url) {
} @Throws(IOException::class)
override fun onExecute(): Int {
@Override request = request.newBuilder()
public int onExecute() throws IOException { .post(postRequestBody)
mRequest = mRequest.newBuilder() .build()
.post(mRequestBody) return super.onExecute()
.build();
return super.onExecute();
} }
} }

View File

@ -0,0 +1,46 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.nonwebdav
import okhttp3.RequestBody
import java.io.IOException
import java.net.URL
/**
* OkHttp put calls wrapper
*
* @author David González Verdugo
*/
class PutMethod(
url: URL,
private val putRequestBody: RequestBody
) : HttpMethod(url) {
@Throws(IOException::class)
override fun onExecute(): Int {
request = request.newBuilder()
.put(putRequestBody)
.build()
return super.onExecute()
}
}

View File

@ -1,57 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav;
import kotlin.Unit;
import java.net.URL;
/**
* Copy calls wrapper
*
* @author Christian Schabesberger
* @author David González Verdugo
*/
public class CopyMethod extends DavMethod {
final String destinationUrl;
final boolean forceOverride;
public CopyMethod(URL url, String destinationUrl, boolean forceOverride) {
super(url);
this.destinationUrl = destinationUrl;
this.forceOverride = forceOverride;
}
@Override
public int onExecute() throws Exception {
mDavResource.copy(destinationUrl, forceOverride, response -> {
mResponse = response;
return Unit.INSTANCE;
});
return super.getStatusCode();
}
}

View File

@ -0,0 +1,51 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav
import okhttp3.Response
import java.net.URL
/**
* Copy calls wrapper
*
* @author Christian Schabesberger
* @author David González Verdugo
*/
class CopyMethod(
val url: URL,
private val destinationUrl: String,
private val forceOverride: Boolean
) : DavMethod(url) {
@Throws(Exception::class)
public override fun onExecute(): Int {
davResource.copy(
destinationUrl,
forceOverride,
super.getRequestHeadersAsHashMap()
) { callBackResponse: Response ->
response = callBackResponse
}
return super.statusCode
}
}

View File

@ -21,13 +21,12 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.webdav
package com.owncloud.android.lib.common.http.methods.webdav;
/** /**
* @author David González Verdugo * @author David González Verdugo
*/ */
public class DavConstants { object DavConstants {
public static final int DEPTH_0 = 0; const val DEPTH_0 = 0
public static final int DEPTH_1 = 1; const val DEPTH_1 = 1
} }

View File

@ -1,162 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.Constants;
import at.bitfire.dav4android.DavOCResource;
import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.exception.RedirectException;
import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import okhttp3.HttpUrl;
import okhttp3.Protocol;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Wrapper to perform WebDAV (dav4android) calls
*
* @author David González Verdugo
*/
public abstract class DavMethod extends HttpBaseMethod {
protected DavOCResource mDavResource;
protected DavMethod(URL url) {
super(url);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(url.toString()),
Constants.INSTANCE.getLog());
}
@Override
public void abort() {
mDavResource.cancelCall();
}
@Override
public int execute() throws Exception {
try {
return onExecute();
} catch (HttpException httpException) {
// Modify responses with information gathered from exceptions
if (httpException instanceof RedirectException) {
mResponse = new Response.Builder()
.header(
HttpConstants.LOCATION_HEADER, ((RedirectException) httpException).getRedirectLocation()
)
.code(httpException.getCode())
.request(mRequest)
.message(httpException.getMessage())
.protocol(Protocol.HTTP_1_1)
.build();
} else if (mResponse != null) {
// The check below should be included in okhttp library, method ResponseBody.create(
// TODO check most recent versions of okhttp to see if this is already fixed and try to update if so
if (mResponse.body().contentType() != null) {
ResponseBody responseBody = ResponseBody.create(
mResponse.body().contentType(),
httpException.getResponseBody()
);
mResponse = mResponse.newBuilder()
.body(responseBody)
.build();
}
}
return httpException.getCode();
}
}
//////////////////////////////
// Setter
//////////////////////////////
// Connection parameters
@Override
public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
super.setReadTimeout(readTimeout, timeUnit);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public void setConnectionTimeout(long connectionTimeout, TimeUnit timeUnit) {
super.setConnectionTimeout(connectionTimeout, timeUnit);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public void setFollowRedirects(boolean followRedirects) {
super.setFollowRedirects(followRedirects);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public void setUrl(HttpUrl url) {
super.setUrl(url);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public boolean getRetryOnConnectionFailure() {
return false; //TODO: implement me
}
//////////////////////////////
// Getter
//////////////////////////////
@Override
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
super.setRetryOnConnectionFailure(retryOnConnectionFailure);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public boolean isAborted() {
return mDavResource.isCallAborted();
}
}

View File

@ -0,0 +1,161 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav
import at.bitfire.dav4jvm.Dav4jvm.log
import at.bitfire.dav4jvm.DavOCResource
import at.bitfire.dav4jvm.exception.HttpException
import at.bitfire.dav4jvm.exception.RedirectException
import com.owncloud.android.lib.common.http.HttpConstants
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Protocol
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import java.net.MalformedURLException
import java.net.URL
import java.util.concurrent.TimeUnit
/**
* Wrapper to perform WebDAV (dav4android) calls
*
* @author David González Verdugo
*/
abstract class DavMethod protected constructor(url: URL) : HttpBaseMethod(url) {
protected var davResource: DavOCResource
override lateinit var response: Response
init {
val httpUrl = url.toHttpUrlOrNull() ?: throw MalformedURLException()
davResource = DavOCResource(
okHttpClient,
httpUrl,
log
)
}
override fun abort() {
davResource.cancelCall()
}
@Throws(Exception::class)
override fun execute(): Int {
return try {
onExecute()
} catch (httpException: HttpException) {
// Modify responses with information gathered from exceptions
if (httpException is RedirectException) {
response = Response.Builder()
.header(
HttpConstants.LOCATION_HEADER, httpException.redirectLocation
)
.code(httpException.code)
.request(request)
.message(httpException.message ?: "")
.protocol(Protocol.HTTP_1_1)
.build()
} else {
// The check below should be included in okhttp library, method ResponseBody.create(
// TODO check most recent versions of okhttp to see if this is already fixed and try to update if so
if (response.body?.contentType() != null) {
val responseBody = (httpException.responseBody ?: "").toResponseBody(response.body?.contentType())
response = response.newBuilder()
.body(responseBody)
.build()
}
}
httpException.code
}
}
//////////////////////////////
// Setter
//////////////////////////////
// Connection parameters
override fun setReadTimeout(readTimeout: Long, timeUnit: TimeUnit) {
super.setReadTimeout(readTimeout, timeUnit)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
override fun setConnectionTimeout(
connectionTimeout: Long,
timeUnit: TimeUnit
) {
super.setConnectionTimeout(connectionTimeout, timeUnit)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
override fun setFollowRedirects(followRedirects: Boolean) {
super.setFollowRedirects(followRedirects)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
override fun setUrl(url: HttpUrl) {
super.setUrl(url)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
override fun setRequestHeader(name: String, value: String) {
super.setRequestHeader(name, value)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
//////////////////////////////
// Getter
//////////////////////////////
override fun setRetryOnConnectionFailure(retryOnConnectionFailure: Boolean) {
super.setRetryOnConnectionFailure(retryOnConnectionFailure)
davResource = DavOCResource(
okHttpClient,
request.url,
log
)
}
override val isAborted: Boolean
get() = davResource.isCallAborted()
}

View File

@ -1,15 +0,0 @@
package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.PropertyUtils;
public class DavUtils {
public static final Property.Name[] getAllPropset() {
return PropertyUtils.INSTANCE.getAllPropSet();
}
public static final Property.Name[] getQuotaPropSet() {
return PropertyUtils.INSTANCE.getQuotaPropset();
}
}

View File

@ -21,24 +21,16 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.webdav
package com.owncloud.android.lib.common.http.methods.nonwebdav; import at.bitfire.dav4jvm.Property
import at.bitfire.dav4jvm.PropertyUtils.getAllPropSet
import at.bitfire.dav4jvm.PropertyUtils.getQuotaPropset
import java.io.IOException; object DavUtils {
import java.net.URL; @JvmStatic val allPropset: Array<Property.Name>
get() = getAllPropSet()
public class PutMethod extends HttpMethod { val quotaPropSet: Array<Property.Name>
get() = getQuotaPropset()
public PutMethod(URL url) {
super(url);
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.put(mRequestBody)
.build();
return super.onExecute();
}
} }

View File

@ -21,12 +21,10 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common.http.methods.webdav
package com.owncloud.android.lib.common.http.methods.webdav; import okhttp3.Response
import java.net.URL
import kotlin.Unit;
import java.net.URL;
/** /**
* MkCol calls wrapper * MkCol calls wrapper
@ -34,18 +32,15 @@ import java.net.URL;
* @author Christian Schabesberger * @author Christian Schabesberger
* @author David González Verdugo * @author David González Verdugo
*/ */
public class MkColMethod extends DavMethod { class MkColMethod(url: URL) : DavMethod(url) {
public MkColMethod(URL url) { @Throws(Exception::class)
super(url); public override fun onExecute(): Int {
davResource.mkCol(
xmlBody = null,
listOfHeaders = super.getRequestHeadersAsHashMap()
) { callBackResponse: Response ->
response = callBackResponse
} }
return super.statusCode
@Override
public int onExecute() throws Exception {
mDavResource.mkCol(null, response -> {
mResponse = response;
return Unit.INSTANCE;
});
return super.getStatusCode();
} }
} }

View File

@ -1,61 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav;
import com.owncloud.android.lib.common.http.HttpConstants;
import kotlin.Unit;
import java.net.URL;
/**
* Move calls wrapper
*
* @author Christian Schabesberger
* @author David González Verdugo
*/
public class MoveMethod extends DavMethod {
final String destinationUrl;
final boolean forceOverride;
public MoveMethod(URL url, String destinationUrl, boolean forceOverride) {
super(url);
this.destinationUrl = destinationUrl;
this.forceOverride = forceOverride;
}
@Override
public int onExecute() throws Exception {
mDavResource.move(
destinationUrl,
forceOverride,
super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER),
super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> {
mResponse = response;
return Unit.INSTANCE;
});
return super.getStatusCode();
}
}

View File

@ -0,0 +1,52 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav
import okhttp3.Response
import java.net.URL
/**
* Move calls wrapper
*
* @author Christian Schabesberger
* @author David González Verdugo
*/
class MoveMethod(
url: URL,
private val destinationUrl: String,
private val forceOverride: Boolean
) : DavMethod(url) {
@Throws(Exception::class)
public override fun onExecute(): Int {
davResource.move(
destinationUrl,
forceOverride,
super.getRequestHeadersAsHashMap()
) { callBackResponse: Response ->
response = callBackResponse
}
return super.statusCode
}
}

View File

@ -1,94 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.Response;
import at.bitfire.dav4android.exception.DavException;
import kotlin.Unit;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Propfind calls wrapper
*
* @author David González Verdugo
*/
public class PropfindMethod extends DavMethod {
// request
private final int mDepth;
private final Property.Name[] mPropertiesToRequest;
// response
private final List<Response> mMembers;
private Response mRoot;
public PropfindMethod(URL url, int depth, Property.Name[] propertiesToRequest) {
super(url);
mDepth = depth;
mPropertiesToRequest = propertiesToRequest;
mMembers = new ArrayList<>();
mRoot = null;
}
@Override
public int onExecute() throws IOException, DavException {
mDavResource.propfind(mDepth, mPropertiesToRequest,
(Response response, Response.HrefRelation hrefRelation) -> {
switch (hrefRelation) {
case MEMBER:
mMembers.add(response);
break;
case SELF:
mRoot = response;
break;
case OTHER:
default:
}
return Unit.INSTANCE;
}, response -> {
mResponse = response;
return Unit.INSTANCE;
});
return getStatusCode();
}
public int getDepth() {
return mDepth;
}
public List<Response> getMembers() {
return mMembers;
}
public Response getRoot() {
return mRoot;
}
}

View File

@ -0,0 +1,72 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav
import at.bitfire.dav4jvm.Property
import at.bitfire.dav4jvm.Response
import at.bitfire.dav4jvm.Response.HrefRelation
import at.bitfire.dav4jvm.exception.DavException
import java.io.IOException
import java.net.URL
/**
* Propfind calls wrapper
*
* @author David González Verdugo
*/
class PropfindMethod(
url: URL,
private val depth: Int,
private val propertiesToRequest: Array<Property.Name>
) : DavMethod(url) {
// response
val members: MutableList<Response>
var root: Response?
private set
@Throws(IOException::class, DavException::class)
public override fun onExecute(): Int {
davResource.propfind(
depth = depth,
reqProp = *propertiesToRequest,
listOfHeaders = super.getRequestHeadersAsHashMap(),
callback = { response: Response, hrefRelation: HrefRelation? ->
when (hrefRelation) {
HrefRelation.MEMBER -> members.add(response)
HrefRelation.SELF -> this.root = response
HrefRelation.OTHER -> {
}
}
}, rawCallback = { callBackResponse: okhttp3.Response ->
response = callBackResponse
})
return statusCode
}
init {
members = arrayListOf()
this.root = null
}
}

View File

@ -1,61 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.exception.HttpException;
import com.owncloud.android.lib.common.http.HttpConstants;
import kotlin.Unit;
import java.io.IOException;
import java.net.URL;
/**
* Put calls wrapper
*
* @author David González Verdugo
*/
public class PutMethod extends DavMethod {
public PutMethod(URL url) {
super(url);
}
;
@Override
public int onExecute() throws IOException, HttpException {
mDavResource.put(
mRequestBody,
super.getRequestHeader(HttpConstants.IF_MATCH_HEADER),
super.getRequestHeader(HttpConstants.CONTENT_TYPE_HEADER),
super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER),
super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> {
mResponse = response;
return Unit.INSTANCE;
});
return super.getStatusCode();
}
}

View File

@ -0,0 +1,52 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.http.methods.webdav
import at.bitfire.dav4jvm.exception.HttpException
import com.owncloud.android.lib.common.http.HttpConstants
import okhttp3.RequestBody
import java.io.IOException
import java.net.URL
/**
* Put calls wrapper
*
* @author David González Verdugo
*/
class PutMethod(
url: URL,
private val putRequestBody: RequestBody
) : DavMethod(url) {
@Throws(IOException::class, HttpException::class)
public override fun onExecute(): Int {
davResource.put(
putRequestBody,
super.getRequestHeader(HttpConstants.IF_MATCH_HEADER),
getRequestHeadersAsHashMap()
) { callBackResponse ->
response = callBackResponse
}
return super.statusCode
}
}

View File

@ -45,6 +45,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
private X509TrustManager mStandardTrustManager; private X509TrustManager mStandardTrustManager;
private KeyStore mKnownServersKeyStore; private KeyStore mKnownServersKeyStore;
/** /**
* Constructor for AdvancedX509TrustManager * Constructor for AdvancedX509TrustManager
* *
@ -66,7 +67,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
* @return The first X509TrustManager found in factory. * @return The first X509TrustManager found in factory.
*/ */
private X509TrustManager findX509TrustManager(TrustManagerFactory factory) { private X509TrustManager findX509TrustManager(TrustManagerFactory factory) {
TrustManager tms[] = factory.getTrustManagers(); TrustManager[] tms = factory.getTrustManagers();
for (TrustManager tm : tms) { for (TrustManager tm : tms) {
if (tm instanceof X509TrustManager) { if (tm instanceof X509TrustManager) {
return (X509TrustManager) tm; return (X509TrustManager) tm;

View File

@ -44,9 +44,9 @@ import java.util.Set;
*/ */
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer { public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
final Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
protected File mFile; protected File mFile;
private MediaType mContentType; private MediaType mContentType;
final Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
public FileRequestBody(File file, MediaType contentType) { public FileRequestBody(File file, MediaType contentType) {
mFile = file; mFile = file;

View File

@ -34,9 +34,6 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0;
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_PATH_4_0_AND_LATER;
public class WebdavUtils { public class WebdavUtils {
private static final SimpleDateFormat[] DATETIME_FORMATS = { private static final SimpleDateFormat[] DATETIME_FORMATS = {

View File

@ -27,8 +27,8 @@ package com.owncloud.android.lib.common.operations;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4jvm.exception.DavException;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4jvm.exception.HttpException;
import com.owncloud.android.lib.common.accounts.AccountUtils; 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;

View File

@ -25,7 +25,7 @@ package com.owncloud.android.lib.resources.files
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.DavUtils import com.owncloud.android.lib.common.http.methods.webdav.DavUtils.allPropset
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod 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.RedirectionPath
import com.owncloud.android.lib.common.network.WebdavUtils import com.owncloud.android.lib.common.network.WebdavUtils
@ -66,7 +66,7 @@ class CheckPathExistenceRemoteOperation(
if (isUserLogged) client.baseFilesWebDavUri.toString() if (isUserLogged) client.baseFilesWebDavUri.toString()
else client.userFilesWebDavUri.toString() + WebdavUtils.encodePath(remotePath) else client.userFilesWebDavUri.toString() + WebdavUtils.encodePath(remotePath)
val propFindMethod = PropfindMethod(URL(stringUrl), 0, DavUtils.getAllPropset()).apply { val propFindMethod = PropfindMethod(URL(stringUrl), 0, allPropset).apply {
setReadTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS) setReadTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
setConnectionTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS) setConnectionTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
} }

View File

@ -29,12 +29,11 @@ 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 FINAL_CHUNKS_FILE = ".file"; public static final String FINAL_CHUNKS_FILE = ".file";
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(File.separator) ? parentPath : parentPath + File.separator;
return parentPath; return parentPath;
} }
@ -42,14 +41,12 @@ public class FileUtils {
* Validate the fileName to detect if contains any forbidden character: / , \ , < , > , * Validate the fileName to detect if contains any forbidden character: / , \ , < , > ,
* : , " , | , ? , * * : , " , | , ? , *
* *
* @param fileName
* @return
*/ */
public static boolean isValidName(String fileName) { public static boolean isValidName(String fileName) {
boolean result = true; boolean result = true;
Timber.d("fileName =======%s", fileName); Timber.d("fileName =======%s", fileName);
if (fileName.contains(PATH_SEPARATOR)) { if (fileName.contains(File.separator)) {
result = false; result = false;
} }
return result; return result;

View File

@ -24,7 +24,7 @@
package com.owncloud.android.lib.resources.files; package com.owncloud.android.lib.resources.files;
import at.bitfire.dav4android.Response; import at.bitfire.dav4jvm.Response;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
@ -122,7 +122,6 @@ public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteF
} }
private boolean isSuccess(int status) { private boolean isSuccess(int status) {
return status == HttpConstants.HTTP_MULTI_STATUS || return status == HttpConstants.HTTP_MULTI_STATUS || status == HttpConstants.HTTP_OK;
status == HttpConstants.HTTP_OK;
} }
} }

View File

@ -27,20 +27,11 @@ package com.owncloud.android.lib.resources.files;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import at.bitfire.dav4android.Property; import at.bitfire.dav4jvm.Property;
import at.bitfire.dav4android.Response; import at.bitfire.dav4jvm.Response;
import at.bitfire.dav4android.property.CreationDate; import at.bitfire.dav4jvm.property.*;
import at.bitfire.dav4android.property.GetContentLength;
import at.bitfire.dav4android.property.GetContentType;
import at.bitfire.dav4android.property.GetETag;
import at.bitfire.dav4android.property.GetLastModified;
import at.bitfire.dav4android.property.QuotaAvailableBytes;
import at.bitfire.dav4android.property.QuotaUsedBytes;
import at.bitfire.dav4android.property.owncloud.OCId;
import at.bitfire.dav4android.property.owncloud.OCPermissions;
import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
import at.bitfire.dav4android.property.owncloud.OCSize;
import java.io.File;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@ -92,13 +83,13 @@ public class RemoteFile implements Parcelable, Serializable {
/** /**
* Create new {@link RemoteFile} with given path. * Create new {@link RemoteFile} with given path.
* <p> * <p>
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'. * The path received must be URL-decoded. Path separator must be File.separator, and it must be the first character in 'path'.
* *
* @param path The remote path of the file. * @param path The remote path of the file.
*/ */
public RemoteFile(String path) { public RemoteFile(String path) {
resetData(); resetData();
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) { if (path == null || path.length() <= 0 || !path.startsWith(File.separator)) {
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path); throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
} }
mRemotePath = path; mRemotePath = path;

View File

@ -41,7 +41,7 @@ class RemoteFileUtil {
*/ */
fun getRemotePathFromUrl(url: HttpUrl, userId: String): String? { fun getRemotePathFromUrl(url: HttpUrl, userId: String): String? {
val davFilesPath = OwnCloudClient.WEBDAV_FILES_PATH_4_0 + userId val davFilesPath = OwnCloudClient.WEBDAV_FILES_PATH_4_0 + userId
val absoluteDavPath = Uri.decode(url.encodedPath()) val absoluteDavPath = Uri.decode(url.encodedPath)
val pathToOc = absoluteDavPath.split(davFilesPath)[0] val pathToOc = absoluteDavPath.split(davFilesPath)[0]
return absoluteDavPath.replace(pathToOc + davFilesPath, "") return absoluteDavPath.replace(pathToOc + davFilesPath, "")
} }

View File

@ -68,11 +68,10 @@ public class RenameRemoteFileOperation extends RemoteOperation {
mNewName = newName; mNewName = newName;
String parent = (new File(mOldRemotePath)).getParent(); String parent = (new File(mOldRemotePath)).getParent();
parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent + parent = (parent.endsWith(File.separator)) ? parent : parent + File.separator;
FileUtils.PATH_SEPARATOR;
mNewRemotePath = parent + mNewName; mNewRemotePath = parent + mNewName;
if (isFolder) { if (isFolder) {
mNewRemotePath += FileUtils.PATH_SEPARATOR; mNewRemotePath += File.separator;
} }
} }

View File

@ -84,10 +84,6 @@ public class UploadRemoteFileOperation extends RemoteOperation {
RemoteOperationResult result; RemoteOperationResult result;
try { try {
mPutMethod = new PutMethod(
new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)));
mPutMethod.setRetryOnConnectionFailure(false);
if (mCancellationRequested.get()) { if (mCancellationRequested.get()) {
// the operation was cancelled before getting it's turn to be executed in the queue of uploads // the operation was cancelled before getting it's turn to be executed in the queue of uploads
@ -125,6 +121,11 @@ public class UploadRemoteFileOperation extends RemoteOperation {
mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners); mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners);
} }
mPutMethod = new PutMethod(
new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)), mFileRequestBody);
mPutMethod.setRetryOnConnectionFailure(false);
if (mRequiredEtag != null && mRequiredEtag.length() > 0) { if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
mPutMethod.addRequestHeader(HttpConstants.IF_MATCH_HEADER, mRequiredEtag); mPutMethod.addRequestHeader(HttpConstants.IF_MATCH_HEADER, mRequiredEtag);
} }
@ -132,8 +133,6 @@ public class UploadRemoteFileOperation extends RemoteOperation {
mPutMethod.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length())); mPutMethod.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length()));
mPutMethod.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp); mPutMethod.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
mPutMethod.setRequestBody(mFileRequestBody);
int status = client.executeHttpMethod(mPutMethod); int status = client.executeHttpMethod(mPutMethod);
if (isSuccess(status)) { if (isSuccess(status)) {

View File

@ -29,7 +29,6 @@ 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.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 timber.log.Timber;
@ -82,18 +81,11 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
} }
long offset = 0; long offset = 0;
String uriPrefix = client.getUploadsWebDavUri() + FileUtils.PATH_SEPARATOR + String.valueOf(mTransferId); String uriPrefix = client.getUploadsWebDavUri() + File.separator + mTransferId;
long totalLength = fileToUpload.length(); long totalLength = fileToUpload.length();
long chunkCount = (long) Math.ceil((double) totalLength / CHUNK_SIZE); long chunkCount = (long) Math.ceil((double) totalLength / CHUNK_SIZE);
for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++, offset += CHUNK_SIZE) { for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++, offset += CHUNK_SIZE) {
mPutMethod = new PutMethod(
new URL(uriPrefix + FileUtils.PATH_SEPARATOR + chunkIndex)
);
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
}
((ChunkFromFileRequestBody) mFileRequestBody).setOffset(offset); ((ChunkFromFileRequestBody) mFileRequestBody).setOffset(offset);
@ -101,6 +93,12 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
result = new RemoteOperationResult<>(new OperationCancelledException()); result = new RemoteOperationResult<>(new OperationCancelledException());
break; break;
} else { } else {
mPutMethod = new PutMethod(new URL(uriPrefix + File.separator + chunkIndex), mFileRequestBody);
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
}
if (chunkIndex == chunkCount - 1) { if (chunkIndex == chunkCount - 1) {
// Added a high timeout to the last chunk due to when the last chunk // Added a high timeout to the last chunk due to when the last chunk
// arrives to the server with the last PUT, all chunks get assembled // arrives to the server with the last PUT, all chunks get assembled
@ -108,8 +106,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
mPutMethod.setReadTimeout(LAST_CHUNK_TIMEOUT, TimeUnit.MILLISECONDS); mPutMethod.setReadTimeout(LAST_CHUNK_TIMEOUT, TimeUnit.MILLISECONDS);
} }
mPutMethod.setRequestBody(mFileRequestBody);
status = client.executeHttpMethod(mPutMethod); status = client.executeHttpMethod(mPutMethod);
Timber.d("Upload of " + mLocalPath + " to " + mRemotePath + Timber.d("Upload of " + mLocalPath + " to " + mRemotePath +

View File

@ -116,9 +116,7 @@ class CreateRemoteShareOperation(
val uriBuilder = requestUri.buildUpon() val uriBuilder = requestUri.buildUpon()
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH) uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH)
val postMethod = PostMethod(URL(uriBuilder.build().toString())) val postMethod = PostMethod(URL(uriBuilder.build().toString()), formBodyBuilder.build())
postMethod.setRequestBody(formBodyBuilder.build())
postMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8) postMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8)
postMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) postMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
@ -133,7 +131,7 @@ class CreateRemoteShareOperation(
parser.oneOrMoreSharesRequired = true parser.oneOrMoreSharesRequired = true
parser.ownCloudVersion = client.ownCloudVersion parser.ownCloudVersion = client.ownCloudVersion
parser.serverBaseUri = client.baseUri parser.serverBaseUri = client.baseUri
result = parser.parse(postMethod.responseBodyAsString) result = parser.parse(postMethod.getResponseBodyAsString())
if (result.isSuccess && retrieveShareDetails) { if (result.isSuccess && retrieveShareDetails) {
// retrieve more info - POST only returns the index of the new share // retrieve more info - POST only returns the index of the new share
@ -145,7 +143,7 @@ class CreateRemoteShareOperation(
} }
} else { } else {
result = parser.parse(postMethod.responseBodyAsString) result = parser.parse(postMethod.getResponseBodyAsString())
} }
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -98,7 +98,7 @@ class GetRemoteShareesOperation
getMethod.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.getResponseBodyAsString()
if (isSuccess(status)) { if (isSuccess(status)) {
Timber.d("Successful response: $response") Timber.d("Successful response: $response")

View File

@ -86,10 +86,10 @@ class GetRemoteSharesForFileOperation(
) )
parser.ownCloudVersion = client.ownCloudVersion parser.ownCloudVersion = client.ownCloudVersion
parser.serverBaseUri = client.baseUri parser.serverBaseUri = client.baseUri
result = parser.parse(getMethod.responseBodyAsString) result = parser.parse(getMethod.getResponseBodyAsString())
if (result.isSuccess) { if (result.isSuccess) {
Timber.d("Got " + result.data.shares.size + " shares") Timber.d("Got ${result.data.shares.size} shares")
} }
} else { } else {
result = RemoteOperationResult(getMethod) result = RemoteOperationResult(getMethod)

View File

@ -25,6 +25,7 @@
package com.owncloud.android.lib.resources.shares package com.owncloud.android.lib.resources.shares
import com.owncloud.android.lib.resources.files.FileUtils import com.owncloud.android.lib.resources.files.FileUtils
import java.io.File
/** /**
* Contains the data of a Share from the Share API * Contains the data of a Share from the Share API
@ -48,7 +49,7 @@ data class RemoteShare(
var permissions: Int = DEFAULT_PERMISSION, var permissions: Int = DEFAULT_PERMISSION,
var sharedDate: Long = INIT_SHARED_DATE, var sharedDate: Long = INIT_SHARED_DATE,
var expirationDate: Long = INIT_EXPIRATION_DATE_IN_MILLIS, var expirationDate: Long = INIT_EXPIRATION_DATE_IN_MILLIS,
var isFolder: Boolean = path.endsWith(FileUtils.PATH_SEPARATOR), var isFolder: Boolean = path.endsWith(File.separator),
var userId: Long = 0, var userId: Long = 0,
val isValid: Boolean = id > -1 val isValid: Boolean = id > -1
) { ) {

View File

@ -73,9 +73,9 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
val parser = ShareToRemoteOperationResultParser( val parser = ShareToRemoteOperationResultParser(
ShareXMLParser() ShareXMLParser()
) )
result = parser.parse(deleteMethod.responseBodyAsString) result = parser.parse(deleteMethod.getResponseBodyAsString())
Timber.d("Unshare " + remoteShareId + ": " + result.logMessage) Timber.d("Unshare $remoteShareId: ${result.logMessage}")
} else { } else {
result = RemoteOperationResult(deleteMethod) result = RemoteOperationResult(deleteMethod)
@ -83,7 +83,7 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
} catch (e: Exception) { } catch (e: Exception) {
result = RemoteOperationResult(e) result = RemoteOperationResult(e)
Timber.e(e, "Unshare Link Exception " + result.logMessage) Timber.e(e, "Unshare Link Exception ${result.logMessage}")
} }
return result return result

View File

@ -25,14 +25,11 @@
package com.owncloud.android.lib.resources.shares package com.owncloud.android.lib.resources.shares
import android.util.Xml import android.util.Xml
import com.owncloud.android.lib.common.network.WebdavUtils import com.owncloud.android.lib.common.network.WebdavUtils
import com.owncloud.android.lib.resources.files.FileUtils
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException import org.xmlpull.v1.XmlPullParserException
import org.xmlpull.v1.XmlPullParserFactory import org.xmlpull.v1.XmlPullParserFactory
import java.io.File
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.util.ArrayList import java.util.ArrayList
@ -330,9 +327,9 @@ class ShareXMLParser {
private fun fixPathForFolder(share: RemoteShare) { private fun fixPathForFolder(share: RemoteShare) {
if (share.isFolder && share.path.isNotEmpty() && if (share.isFolder && share.path.isNotEmpty() &&
!share.path.endsWith(FileUtils.PATH_SEPARATOR) !share.path.endsWith(File.separator)
) { ) {
share.path = share.path + FileUtils.PATH_SEPARATOR share.path = share.path + File.separator
} }
} }

View File

@ -143,9 +143,7 @@ class UpdateRemoteShareOperation
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH) uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH)
uriBuilder.appendEncodedPath(remoteId.toString()) uriBuilder.appendEncodedPath(remoteId.toString())
val putMethod = PutMethod(URL(uriBuilder.build().toString())) val putMethod = PutMethod(URL(uriBuilder.build().toString()), formBodyBuilder.build())
putMethod.setRequestBody(formBodyBuilder.build())
putMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8) putMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8)
putMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) putMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
@ -158,12 +156,12 @@ class UpdateRemoteShareOperation
) )
if (!isSuccess(status)) { if (!isSuccess(status)) {
return parser.parse(putMethod.responseBodyAsString) return parser.parse(putMethod.getResponseBodyAsString())
} }
parser.ownCloudVersion = client.ownCloudVersion parser.ownCloudVersion = client.ownCloudVersion
parser.serverBaseUri = client.baseUri parser.serverBaseUri = client.baseUri
result = parser.parse(putMethod.responseBodyAsString) result = parser.parse(putMethod.getResponseBodyAsString())
if (result.isSuccess && retrieveShareDetails) { if (result.isSuccess && retrieveShareDetails) {
// retrieve more info - PUT only returns the index of the new share // retrieve more info - PUT only returns the index of the new share

View File

@ -65,7 +65,7 @@ class GetRemoteCapabilitiesOperation : RemoteOperation<RemoteCapability>() {
} }
val status = client.executeHttpMethod(getMethod) val status = client.executeHttpMethod(getMethod)
val response = getMethod.responseBodyAsString val response = getMethod.getResponseBodyAsString()
if (status == HttpConstants.HTTP_OK) { if (status == HttpConstants.HTTP_OK) {
Timber.d("Successful response $response") Timber.d("Successful response $response")

View File

@ -108,7 +108,7 @@ class GetRemoteStatusOperation : RemoteOperation<OwnCloudVersion>() {
} }
if (isSuccess(status)) { if (isSuccess(status)) {
val respJSON = JSONObject(getMethod.responseBodyAsString) val respJSON = JSONObject(getMethod.getResponseBodyAsString())
if (!respJSON.getBoolean(NODE_INSTALLED)) { if (!respJSON.getBoolean(NODE_INSTALLED)) {
latestResult = RemoteOperationResult(ResultCode.INSTANCE_NOT_CONFIGURED) latestResult = RemoteOperationResult(ResultCode.INSTANCE_NOT_CONFIGURED)
} else { } else {

View File

@ -38,6 +38,8 @@ class OwnCloudVersion(version: String) : Comparable<OwnCloudVersion>, Parcelable
var isVersionValid: Boolean = false var isVersionValid: Boolean = false
set set
var isVersionHidden: Boolean = false
val version: String val version: String
get() = if (isVersionValid) { get() = if (isVersionValid) {
toString() toString()
@ -55,6 +57,7 @@ class OwnCloudVersion(version: String) : Comparable<OwnCloudVersion>, Parcelable
var versionToParse = version var versionToParse = version
mVersion = 0 mVersion = 0
isVersionValid = false isVersionValid = false
isVersionHidden = version.isBlank()
val countDots = versionToParse.length - versionToParse.replace(".", "").length val countDots = versionToParse.length - versionToParse.replace(".", "").length
// Complete the version. Version must have 3 dots // Complete the version. Version must have 3 dots

View File

@ -21,6 +21,7 @@ package com.owncloud.android.lib.resources.status.services.implementation
import android.net.Uri 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.OwnCloudCredentialsFactory.getAnonymousCredentials
import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.status.services.ServerInfoService import com.owncloud.android.lib.resources.status.services.ServerInfoService
import com.owncloud.android.lib.resources.files.CheckPathExistenceRemoteOperation import com.owncloud.android.lib.resources.files.CheckPathExistenceRemoteOperation
@ -38,6 +39,6 @@ class OCServerInfoService : ServerInfoService {
GetRemoteStatusOperation().execute(createClientFromPath(path)) GetRemoteStatusOperation().execute(createClientFromPath(path))
private fun createClientFromPath(path: String): OwnCloudClient { private fun createClientFromPath(path: String): OwnCloudClient {
return OwnCloudClient(Uri.parse(path)) return OwnCloudClient(Uri.parse(path)).apply { credentials = getAnonymousCredentials() }
} }
} }

View File

@ -1,185 +0,0 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.resources.users;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import timber.log.Timber;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/**
* Gets avatar about the user logged in, if available
*
* @author David A. Velasco
* @author David González Verdugo
*/
public class GetRemoteUserAvatarOperation extends RemoteOperation<GetRemoteUserAvatarOperation.ResultData> {
private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/";
/**
* Desired size in pixels of the squared image
*/
private int mDimension;
public GetRemoteUserAvatarOperation(int dimension) {
mDimension = dimension;
}
@Override
protected RemoteOperationResult<ResultData> run(OwnCloudClient client) {
GetMethod getMethod = null;
RemoteOperationResult<ResultData> result;
InputStream inputStream = null;
BufferedInputStream bis = null;
ByteArrayOutputStream bos = null;
try {
final String url = client.getBaseUri() + NON_OFFICIAL_AVATAR_PATH + client.getCredentials().getUsername() + "/" + mDimension;
Timber.d("avatar URI: %s", url);
getMethod = new GetMethod(new URL(url));
int status = client.executeHttpMethod(getMethod);
if (isSuccess(status)) {
// find out size of file to read
int totalToTransfer = 0;
String contentLength = getMethod.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER);
if (contentLength != null && contentLength.length() > 0) {
totalToTransfer = Integer.parseInt(contentLength);
}
// find out MIME-type!
String mimeType;
String contentType = getMethod.getResponseHeader(HttpConstants.CONTENT_TYPE_HEADER);
if (contentType == null || !contentType.startsWith("image")) {
Timber.w("Not an image, failing with no avatar");
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.FILE_NOT_FOUND);
return result;
}
mimeType = contentType;
/// download will be performed to a buffer
inputStream = getMethod.getResponseBodyAsStream();
bis = new BufferedInputStream(inputStream);
bos = new ByteArrayOutputStream(totalToTransfer);
byte[] bytes = new byte[4096];
int readResult;
while ((readResult = bis.read(bytes)) != -1) {
bos.write(bytes, 0, readResult);
}
// TODO check total bytes transferred?
// find out etag
String etag = WebdavUtils.getEtagFromResponse(getMethod);
if (etag.length() == 0) {
Timber.w("Could not read Etag from avatar");
}
// Result
result = new RemoteOperationResult<>(OK);
result.setData(new ResultData(bos.toByteArray(), mimeType, etag));
} else {
result = new RemoteOperationResult<>(getMethod);
client.exhaustResponse(getMethod.getResponseBodyAsStream());
}
} catch (Exception e) {
result = new RemoteOperationResult<>(e);
Timber.e(e, "Exception while getting OC user avatar");
} finally {
if (getMethod != null) {
try {
if (inputStream != null) {
client.exhaustResponse(inputStream);
if (bis != null) {
bis.close();
} else {
inputStream.close();
}
}
} catch (IOException i) {
Timber.e(i, "Unexpected exception closing input stream");
}
try {
if (bos != null) {
bos.close();
}
} catch (IOException o) {
Timber.e(o, "Unexpected exception closing output stream");
}
}
}
return result;
}
private boolean isSuccess(int status) {
return (status == HttpConstants.HTTP_OK);
}
public static class ResultData {
private String mEtag;
private String mMimeType;
private byte[] mAvatarData;
ResultData(byte[] avatarData, String mimeType, String etag) {
mAvatarData = avatarData;
mMimeType = (mimeType == null) ? "" : mimeType;
mEtag = (etag == null) ? "" : etag;
}
public String getEtag() {
return mEtag;
}
public String getMimeType() {
return mMimeType;
}
public byte[] getAvatarData() {
return mAvatarData;
}
}
}

View File

@ -0,0 +1,114 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.resources.users
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.http.HttpConstants
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
import com.owncloud.android.lib.common.network.WebdavUtils
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.net.URL
/**
* Gets avatar about the user logged in, if available
*
* @author David A. Velasco
* @author David González Verdugo
*/
class GetRemoteUserAvatarOperation(private val avatarDimension: Int) : RemoteOperation<RemoteAvatarData>() {
override fun run(client: OwnCloudClient): RemoteOperationResult<RemoteAvatarData> {
var inputStream: InputStream? = null
var result: RemoteOperationResult<RemoteAvatarData>
try {
val endPoint =
client.baseUri.toString() + NON_OFFICIAL_AVATAR_PATH + client.credentials.username + File.separator + avatarDimension
Timber.d("avatar URI: %s", endPoint)
val getMethod = GetMethod(URL(endPoint))
val status = client.executeHttpMethod(getMethod)
if (isSuccess(status)) {
// find out size of file to read
val contentLength = getMethod.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER)?.toInt()
// find out MIME-type!
val mimeType = getMethod.getResponseHeader(HttpConstants.CONTENT_TYPE_HEADER)
if (mimeType == null || !mimeType.startsWith("image")) {
Timber.w("Not an image, failing with no avatar")
return RemoteOperationResult(RemoteOperationResult.ResultCode.FILE_NOT_FOUND)
}
/// download will be performed to a buffer
inputStream = getMethod.getResponseBodyAsStream()
val bytesArray = inputStream?.readBytes()?: byteArrayOf()
// TODO check total bytes transferred?
Timber.d("Avatar size: Bytes received ${bytesArray.size} of $contentLength")
// find out etag
val etag = WebdavUtils.getEtagFromResponse(getMethod)
if (etag.isEmpty()) {
Timber.w("Could not read Etag from avatar")
}
// Result
result = RemoteOperationResult(RemoteOperationResult.ResultCode.OK)
result.setData(RemoteAvatarData(bytesArray, mimeType, etag))
} else {
result = RemoteOperationResult(getMethod)
client.exhaustResponse(getMethod.getResponseBodyAsStream())
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Timber.e(e, "Exception while getting OC user avatar")
} finally {
try {
client.exhaustResponse(inputStream)
inputStream?.close()
} catch (i: IOException) {
Timber.e(i, "Unexpected exception closing input stream")
}
}
return result
}
private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK
companion object {
private const val NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/"
}
}

View File

@ -53,7 +53,7 @@ class GetRemoteUserInfoOperation : RemoteOperation<RemoteUserInfo>() {
try { try {
val getMethod = GetMethod(URL(client.baseUri.toString() + OCS_ROUTE)) val getMethod = GetMethod(URL(client.baseUri.toString() + OCS_ROUTE))
val status = client.executeHttpMethod(getMethod) val status = client.executeHttpMethod(getMethod)
val response = getMethod.responseBodyAsString val response = getMethod.getResponseBodyAsString() ?: ""
if (status == HttpConstants.HTTP_OK) { if (status == HttpConstants.HTTP_OK) {
Timber.d("Successful response $response") Timber.d("Successful response $response")

View File

@ -1,185 +0,0 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2020 ownCloud Inc.
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2014 Marcello Steiner
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.resources.users;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.property.QuotaAvailableBytes;
import at.bitfire.dav4android.property.QuotaUsedBytes;
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.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import timber.log.Timber;
import java.net.URL;
import java.util.List;
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/**
* @author marcello
* @author David González Verdugo
*/
public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQuotaOperation.RemoteQuota> {
private String mRemotePath;
/**
* Constructor
*
* @param remotePath Remote path of the file.
*/
public GetRemoteUserQuotaOperation(String remotePath) {
mRemotePath = remotePath;
}
@Override
protected RemoteOperationResult<RemoteQuota> run(OwnCloudClient client) {
RemoteOperationResult<RemoteQuota> result = null;
try {
PropfindMethod propfindMethod = new PropfindMethod(
new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
DEPTH_0,
DavUtils.getQuotaPropSet());
int status = client.executeHttpMethod(propfindMethod);
if (isSuccess(status)) {
RemoteQuota remoteQuota = readData(propfindMethod.getRoot().getProperties());
result = new RemoteOperationResult<>(OK);
// Add data to the result
if (result.isSuccess()) {
result.setData(remoteQuota);
}
} else { // synchronization failed
result = new RemoteOperationResult<>(propfindMethod);
}
} catch (Exception e) {
result = new RemoteOperationResult<>(e);
} finally {
if (result.isSuccess()) {
Timber.i("Get quota from " + mRemotePath + ": " + result.getLogMessage());
} else {
if (result.isException()) {
Timber.e(result.getException(), "Get quota from " + mRemotePath + ": " + result.getLogMessage());
} else {
Timber.e("Get quota from " + mRemotePath + ": " + result.getLogMessage());
}
}
}
return result;
}
private boolean isSuccess(int status) {
return status == HttpConstants.HTTP_MULTI_STATUS || status == HttpConstants.HTTP_OK;
}
/**
* Read the data retrieved from the server about the quota
*
* @param properties WebDAV properties containing quota data
* @return new {@link RemoteQuota} instance representing the data read from the server
*/
private RemoteQuota readData(List<Property> properties) {
long quotaAvailable = 0;
long quotaUsed = 0;
for (Property property : properties) {
if (property instanceof QuotaAvailableBytes) {
quotaAvailable = ((QuotaAvailableBytes) property).getQuotaAvailableBytes();
}
if (property instanceof QuotaUsedBytes) {
quotaUsed = ((QuotaUsedBytes) property).getQuotaUsedBytes();
}
}
// If there's a special case, quota available will contain a negative code
// -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning
// -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space
// -3, UNLIMITED: Quota using all the storage
if (quotaAvailable < 0) {
return new RemoteQuota(
quotaAvailable,
quotaUsed,
0,
0
);
} else {
long totalQuota = quotaAvailable + quotaUsed;
double relativeQuota = (double) (quotaUsed * 100) / totalQuota;
double roundedRelativeQuota = Math.round(relativeQuota * 100) / 100.0d;
return new RemoteQuota(
quotaAvailable,
quotaUsed,
totalQuota,
roundedRelativeQuota
);
}
}
static public class RemoteQuota {
long mFree, mUsed, mTotal;
double mRelative;
public RemoteQuota(long free, long used, long total, double relative) {
mFree = free;
mUsed = used;
mTotal = total;
mRelative = relative;
}
public long getFree() {
return mFree;
}
public long getUsed() {
return mUsed;
}
public long getTotal() {
return mTotal;
}
public double getRelative() {
return mRelative;
}
}
}

View File

@ -0,0 +1,126 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2020 ownCloud Inc.
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2014 Marcello Steiner
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.resources.users
import at.bitfire.dav4jvm.Property
import at.bitfire.dav4jvm.property.QuotaAvailableBytes
import at.bitfire.dav4jvm.property.QuotaUsedBytes
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.http.HttpConstants
import com.owncloud.android.lib.common.http.methods.webdav.DavConstants
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.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
import com.owncloud.android.lib.resources.users.GetRemoteUserQuotaOperation.RemoteQuota
import timber.log.Timber
import java.net.URL
import kotlin.math.roundToLong
/**
* @author marcello
* @author David González Verdugo
*/
class GetRemoteUserQuotaOperation : RemoteOperation<RemoteQuota>() {
override fun run(client: OwnCloudClient): RemoteOperationResult<RemoteQuota> =
try {
val propfindMethod = PropfindMethod(
URL(client.userFilesWebDavUri.toString()),
DavConstants.DEPTH_0,
DavUtils.quotaPropSet
)
with(client.executeHttpMethod(propfindMethod)) {
if (isSuccess(this)) {
RemoteOperationResult<RemoteQuota>(ResultCode.OK).apply {
data = readData(propfindMethod.root?.properties)
}.also {
Timber.i("Get quota completed: ${it.data} and message: ${it.logMessage}")
}
} else { // synchronization failed
RemoteOperationResult<RemoteQuota>(propfindMethod).also {
Timber.e("Get quota without success: ${it.logMessage}")
}
}
}
} catch (e: Exception) {
RemoteOperationResult<RemoteQuota>(e).also {
Timber.e(it.exception, "Get quota: ${it.logMessage}")
}
}
private fun isSuccess(status: Int) = status == HttpConstants.HTTP_MULTI_STATUS || status == HttpConstants.HTTP_OK
/**
* Read the data retrieved from the server about the quota
*
* @param properties WebDAV properties containing quota data
* @return new [RemoteQuota] instance representing the data read from the server
*/
private fun readData(properties: List<Property>?): RemoteQuota {
var quotaAvailable: Long = 0
var quotaUsed: Long = 0
if (properties == null) {
// Should not happen
Timber.d("Unable to get quota")
return RemoteQuota(0, 0, 0, 0.0)
}
for (property in properties) {
if (property is QuotaAvailableBytes) {
quotaAvailable = property.quotaAvailableBytes
}
if (property is QuotaUsedBytes) {
quotaUsed = property.quotaUsedBytes
}
}
Timber.d("Quota used: $quotaUsed, QuotaAvailable: $quotaAvailable")
// If there's a special case, quota available will contain a negative code
// -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning
// -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space
// -3, UNLIMITED: Quota using all the storage
return if (quotaAvailable < 0) {
RemoteQuota(
free = quotaAvailable,
used = quotaUsed,
total = 0,
relative = 0.0
)
} else {
val totalQuota = quotaAvailable + quotaUsed
val roundedRelativeQuota = if (totalQuota > 0) {
val relativeQuota = (quotaUsed * 100).toDouble() / totalQuota
(relativeQuota * 100).roundToLong() / 100.0
} else 0.0
RemoteQuota(quotaAvailable, quotaUsed, totalQuota, roundedRelativeQuota)
}
}
data class RemoteQuota(var free: Long, var used: Long, var total: Long, var relative: Double)
}

View File

@ -0,0 +1,30 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2020 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.owncloud.android.lib.resources.users
data class RemoteAvatarData(
val avatarData: ByteArray = byteArrayOf(),
val mimeType: String = "",
val eTag: String = ""
)

View File

@ -26,8 +26,12 @@ package com.owncloud.android.lib.resources.users.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.users.GetRemoteUserQuotaOperation
import com.owncloud.android.lib.resources.users.RemoteAvatarData
import com.owncloud.android.lib.resources.users.RemoteUserInfo import com.owncloud.android.lib.resources.users.RemoteUserInfo
interface UserService: Service { interface UserService : Service {
fun getUserInfo() : RemoteOperationResult<RemoteUserInfo> fun getUserInfo(): RemoteOperationResult<RemoteUserInfo>
fun getUserQuota(): RemoteOperationResult<GetRemoteUserQuotaOperation.RemoteQuota>
fun getUserAvatar(avatarDimension: Int): RemoteOperationResult<RemoteAvatarData>
} }

View File

@ -21,12 +21,21 @@ package com.owncloud.android.lib.resources.users.services.implementation
import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation
import com.owncloud.android.lib.resources.users.GetRemoteUserQuotaOperation
import com.owncloud.android.lib.resources.users.RemoteAvatarData
import com.owncloud.android.lib.resources.users.RemoteUserInfo import com.owncloud.android.lib.resources.users.RemoteUserInfo
import com.owncloud.android.lib.resources.users.services.UserService import com.owncloud.android.lib.resources.users.services.UserService
class OCUserService(override val client: OwnCloudClient) : class OCUserService(override val client: OwnCloudClient) : UserService {
UserService {
override fun getUserInfo(): RemoteOperationResult<RemoteUserInfo> = override fun getUserInfo(): RemoteOperationResult<RemoteUserInfo> =
GetRemoteUserInfoOperation().execute(client) GetRemoteUserInfoOperation().execute(client)
override fun getUserQuota(): RemoteOperationResult<GetRemoteUserQuotaOperation.RemoteQuota> =
GetRemoteUserQuotaOperation().execute(client)
override fun getUserAvatar(avatarDimension: Int): RemoteOperationResult<RemoteAvatarData> =
GetRemoteUserAvatarOperation(avatarDimension).execute(client)
} }

View File

@ -5,11 +5,11 @@ dependencies {
} }
android { android {
compileSdkVersion 28 compileSdkVersion 29
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 29
// This is pretty ugly but manifest placeholders don't seem to work very well when using different modules // 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 // See https://github.com/openid/AppAuth-Android/issues/325

View File

@ -47,7 +47,6 @@ import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
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.resources.files.DownloadRemoteFileOperation; import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation; import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
import com.owncloud.android.lib.resources.files.RemoteFile; import com.owncloud.android.lib.resources.files.RemoteFile;
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation; import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
@ -151,14 +150,14 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
} }
private void startRefresh() { private void startRefresh() {
ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR); ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(File.separator);
refreshOperation.execute(mClient, this, mHandler); refreshOperation.execute(mClient, this, mHandler);
} }
private void startUpload() { private void startUpload() {
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = File.separator + fileToUpload.getName();
String mimeType = getString(R.string.sample_file_mimetype); String mimeType = getString(R.string.sample_file_mimetype);
// Get the last modification date of the file from the file system // Get the last modification date of the file from the file system
@ -174,7 +173,7 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
private void startRemoteDeletion() { private void startRemoteDeletion() {
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = File.separator + fileToUpload.getName();
RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath); RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
removeOperation.execute(mClient, this, mHandler); removeOperation.execute(mClient, this, mHandler);
@ -185,7 +184,7 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
downFolder.mkdir(); downFolder.mkdir();
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = File.separator + fileToUpload.getName();
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath,
downFolder.getAbsolutePath()); downFolder.getAbsolutePath());