1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-07 16:06:08 +00:00

Merge pull request #333 from owncloud/release/1.0.6

[Release] 1.0.6
This commit is contained in:
Abel García de Prada 2020-08-12 13:50:51 +02:00 committed by GitHub
commit f184347235
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 770 additions and 1105 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

@ -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'
@ -29,8 +29,8 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 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

@ -130,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);
} }
@ -177,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) {

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<>();
@ -114,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)
@ -134,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

@ -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()
.delete()
.build()
return super.onExecute()
} }
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.delete()
.build();
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()
.get()
.build()
return super.onExecute()
} }
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.get()
.build();
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 {
request = request.newBuilder()
.post(postRequestBody)
.build()
return super.onExecute()
} }
}
@Override
public int onExecute() throws IOException {
mRequest = mRequest.newBuilder()
.post(mRequestBody)
.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

@ -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,19 +27,9 @@ 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.File;
import java.io.Serializable; import java.io.Serializable;

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

@ -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;
@ -87,11 +86,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
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 + File.separator + chunkIndex));
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
}
((ChunkFromFileRequestBody) mFileRequestBody).setOffset(offset); ((ChunkFromFileRequestBody) mFileRequestBody).setOffset(offset);
@ -99,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
@ -106,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

@ -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

@ -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

@ -58,7 +58,7 @@ class GetRemoteUserAvatarOperation(private val avatarDimension: Int) : RemoteOpe
if (isSuccess(status)) { if (isSuccess(status)) {
// find out size of file to read // find out size of file to read
val contentLength = getMethod.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER).toInt() val contentLength = getMethod.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER)?.toInt()
// find out MIME-type! // find out MIME-type!
val mimeType = getMethod.getResponseHeader(HttpConstants.CONTENT_TYPE_HEADER) val mimeType = getMethod.getResponseHeader(HttpConstants.CONTENT_TYPE_HEADER)
@ -69,8 +69,8 @@ class GetRemoteUserAvatarOperation(private val avatarDimension: Int) : RemoteOpe
} }
/// download will be performed to a buffer /// download will be performed to a buffer
inputStream = getMethod.responseBodyAsStream inputStream = getMethod.getResponseBodyAsStream()
val bytesArray = inputStream.readBytes() val bytesArray = inputStream?.readBytes()?: byteArrayOf()
// TODO check total bytes transferred? // TODO check total bytes transferred?
Timber.d("Avatar size: Bytes received ${bytesArray.size} of $contentLength") Timber.d("Avatar size: Bytes received ${bytesArray.size} of $contentLength")
@ -87,7 +87,7 @@ class GetRemoteUserAvatarOperation(private val avatarDimension: Int) : RemoteOpe
} else { } else {
result = RemoteOperationResult(getMethod) result = RemoteOperationResult(getMethod)
client.exhaustResponse(getMethod.responseBodyAsStream) client.exhaustResponse(getMethod.getResponseBodyAsStream())
} }
} catch (e: Exception) { } catch (e: Exception) {

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

@ -26,9 +26,9 @@
*/ */
package com.owncloud.android.lib.resources.users package com.owncloud.android.lib.resources.users
import at.bitfire.dav4android.Property import at.bitfire.dav4jvm.Property
import at.bitfire.dav4android.property.QuotaAvailableBytes import at.bitfire.dav4jvm.property.QuotaAvailableBytes
import at.bitfire.dav4android.property.QuotaUsedBytes import at.bitfire.dav4jvm.property.QuotaUsedBytes
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.DavConstants import com.owncloud.android.lib.common.http.methods.webdav.DavConstants
@ -52,12 +52,12 @@ class GetRemoteUserQuotaOperation : RemoteOperation<RemoteQuota>() {
val propfindMethod = PropfindMethod( val propfindMethod = PropfindMethod(
URL(client.userFilesWebDavUri.toString()), URL(client.userFilesWebDavUri.toString()),
DavConstants.DEPTH_0, DavConstants.DEPTH_0,
DavUtils.getQuotaPropSet() DavUtils.quotaPropSet
) )
with(client.executeHttpMethod(propfindMethod)) { with(client.executeHttpMethod(propfindMethod)) {
if (isSuccess(this)) { if (isSuccess(this)) {
RemoteOperationResult<RemoteQuota>(ResultCode.OK).apply { RemoteOperationResult<RemoteQuota>(ResultCode.OK).apply {
data = readData(propfindMethod.root.properties) data = readData(propfindMethod.root?.properties)
}.also { }.also {
Timber.i("Get quota completed: ${it.data} and message: ${it.logMessage}") Timber.i("Get quota completed: ${it.data} and message: ${it.logMessage}")
} }
@ -81,9 +81,16 @@ class GetRemoteUserQuotaOperation : RemoteOperation<RemoteQuota>() {
* @param properties WebDAV properties containing quota data * @param properties WebDAV properties containing quota data
* @return new [RemoteQuota] instance representing the data read from the server * @return new [RemoteQuota] instance representing the data read from the server
*/ */
private fun readData(properties: List<Property>): RemoteQuota { private fun readData(properties: List<Property>?): RemoteQuota {
var quotaAvailable: Long = 0 var quotaAvailable: Long = 0
var quotaUsed: 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) { for (property in properties) {
if (property is QuotaAvailableBytes) { if (property is QuotaAvailableBytes) {
quotaAvailable = property.quotaAvailableBytes quotaAvailable = property.quotaAvailableBytes