mirror of
https://github.com/owncloud/android-library.git
synced 2026-08-11 16:33:03 +00:00
Rename library module from lib to owncloudComLibrary
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- ownCloud Android Library is available under MIT license
|
||||
Copyright (C) 2016 ownCloud GmbH.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.owncloud.android.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<!-- USE_CREDENTIALS, MANAGE_ACCOUNTS and AUTHENTICATE_ACCOUNTS are needed for API < 23.
|
||||
In API >= 23 the do not exist anymore -->
|
||||
<uses-permission
|
||||
android:name="android.permission.MANAGE_ACCOUNTS"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
</manifest>
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Dynamic implementation of {@link OwnCloudClientManager}.
|
||||
*
|
||||
* Wraps instances of {@link SingleSessionManager} and {@link SimpleFactoryManager} and delegates on one
|
||||
* or the other depending on the known version of the server corresponding to the {@link OwnCloudAccount}
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
|
||||
public class DynamicSessionManager implements OwnCloudClientManager {
|
||||
|
||||
private SimpleFactoryManager mSimpleFactoryManager = new SimpleFactoryManager();
|
||||
|
||||
private SingleSessionManager mSingleSessionManager = new SingleSessionManager();
|
||||
|
||||
@Override
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
|
||||
throws AccountUtils.AccountNotFoundException,
|
||||
OperationCanceledException, AuthenticatorException, IOException {
|
||||
|
||||
OwnCloudVersion ownCloudVersion = null;
|
||||
if (account.getSavedAccount() != null) {
|
||||
ownCloudVersion = AccountUtils.getServerVersionForAccount(
|
||||
account.getSavedAccount(), context
|
||||
);
|
||||
}
|
||||
|
||||
if (ownCloudVersion != null && ownCloudVersion.isSessionMonitoringSupported()) {
|
||||
return mSingleSessionManager.getClientFor(account, context);
|
||||
} else {
|
||||
return mSimpleFactoryManager.getClientFor(account, context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
OwnCloudClient clientRemovedFromFactoryManager = mSimpleFactoryManager.removeClientFor(account);
|
||||
OwnCloudClient clientRemovedFromSingleSessionManager = mSingleSessionManager.removeClientFor(account);
|
||||
if (clientRemovedFromSingleSessionManager != null) {
|
||||
return clientRemovedFromSingleSessionManager;
|
||||
} else {
|
||||
return clientRemovedFromFactoryManager;
|
||||
}
|
||||
// clientRemoved and clientRemoved2 should not be != null at the same time
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
mSimpleFactoryManager.saveAllClients(context, accountType);
|
||||
mSingleSessionManager.saveAllClients(context, accountType);
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* OwnCloud Account
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class OwnCloudAccount {
|
||||
|
||||
private Uri mBaseUri;
|
||||
|
||||
private OwnCloudCredentials mCredentials;
|
||||
|
||||
private String mDisplayName;
|
||||
|
||||
private String mSavedAccountName;
|
||||
|
||||
private Account mSavedAccount;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for already saved OC accounts.
|
||||
*
|
||||
* Do not use for anonymous credentials.
|
||||
*/
|
||||
public OwnCloudAccount(Account savedAccount, Context context) throws AccountNotFoundException {
|
||||
if (savedAccount == null) {
|
||||
throw new IllegalArgumentException("Parameter 'savedAccount' cannot be null");
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("Parameter 'context' cannot be null");
|
||||
}
|
||||
|
||||
mSavedAccount = savedAccount;
|
||||
mSavedAccountName = savedAccount.name;
|
||||
mCredentials = null; // load of credentials is delayed
|
||||
|
||||
AccountManager ama = AccountManager.get(context.getApplicationContext());
|
||||
String baseUrl = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_OC_BASE_URL);
|
||||
if (baseUrl == null ) {
|
||||
throw new AccountNotFoundException(mSavedAccount, "Account not found", null);
|
||||
}
|
||||
mBaseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(context, mSavedAccount));
|
||||
mDisplayName = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_DISPLAY_NAME);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for non yet saved OC accounts.
|
||||
*
|
||||
* @param baseUri URI to the OC server to get access to.
|
||||
* @param credentials Credentials to authenticate in the server. NULL is valid for anonymous credentials.
|
||||
*/
|
||||
public OwnCloudAccount(Uri baseUri, OwnCloudCredentials credentials) {
|
||||
if (baseUri == null) {
|
||||
throw new IllegalArgumentException("Parameter 'baseUri' cannot be null");
|
||||
}
|
||||
mSavedAccount = null;
|
||||
mSavedAccountName = null;
|
||||
mBaseUri = baseUri;
|
||||
mCredentials = credentials != null ?
|
||||
credentials : OwnCloudCredentialsFactory.getAnonymousCredentials();
|
||||
String username = mCredentials.getUsername();
|
||||
if (username != null) {
|
||||
mSavedAccountName = AccountUtils.buildAccountName(mBaseUri, username);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method for deferred load of account attributes from AccountManager
|
||||
*
|
||||
* @param context
|
||||
* @throws AccountNotFoundException
|
||||
* @throws AuthenticatorException
|
||||
* @throws IOException
|
||||
* @throws OperationCanceledException
|
||||
*/
|
||||
public void loadCredentials(Context context) throws AuthenticatorException,
|
||||
IOException, OperationCanceledException {
|
||||
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("Parameter 'context' cannot be null");
|
||||
}
|
||||
|
||||
if (mSavedAccount != null) {
|
||||
mCredentials = AccountUtils.getCredentialsForAccount(context, mSavedAccount);
|
||||
}
|
||||
}
|
||||
|
||||
public Uri getBaseUri() {
|
||||
return mBaseUri;
|
||||
}
|
||||
|
||||
public OwnCloudCredentials getCredentials() {
|
||||
return mCredentials;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mSavedAccountName;
|
||||
}
|
||||
|
||||
public Account getSavedAccount() {
|
||||
return mSavedAccount;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
if (mDisplayName != null && mDisplayName.length() > 0) {
|
||||
return mDisplayName;
|
||||
} else if (mCredentials != null) {
|
||||
return mCredentials.getUsername();
|
||||
} else if (mSavedAccount != null) {
|
||||
return AccountUtils.getUsernameForAccount(mSavedAccount);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountsException;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials;
|
||||
import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.common.utils.RandomUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
import static com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID;
|
||||
|
||||
public class OwnCloudClient extends HttpClient {
|
||||
|
||||
public static final String WEBDAV_FILES_PATH_4_0 = "/remote.php/dav/files/";
|
||||
public static final String WEBDAV_UPLOADS_PATH_4_0 = "/remote.php/dav/uploads/";
|
||||
public static final String STATUS_PATH = "/status.php";
|
||||
public static final String FILES_WEB_PATH = "/index.php/apps/files";
|
||||
|
||||
private static final String TAG = OwnCloudClient.class.getSimpleName();
|
||||
private static final int MAX_REDIRECTIONS_COUNT = 3;
|
||||
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
||||
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
||||
|
||||
private static byte[] sExhaustBuffer = new byte[1024];
|
||||
private static int sIntanceCounter = 0;
|
||||
private OwnCloudCredentials mCredentials = null;
|
||||
private int mInstanceNumber = 0;
|
||||
private Uri mBaseUri;
|
||||
private OwnCloudVersion mVersion = null;
|
||||
private OwnCloudAccount mAccount;
|
||||
|
||||
/**
|
||||
* {@link @OwnCloudClientManager} holding a reference to this object and delivering it to callers; might be
|
||||
* NULL
|
||||
*/
|
||||
private OwnCloudClientManager mOwnCloudClientManager = null;
|
||||
|
||||
private String mRedirectedLocation;
|
||||
private boolean mFollowRedirects;
|
||||
|
||||
public OwnCloudClient(Uri baseUri) {
|
||||
if (baseUri == null) {
|
||||
throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
|
||||
}
|
||||
mBaseUri = baseUri;
|
||||
|
||||
mInstanceNumber = sIntanceCounter++;
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
|
||||
|
||||
clearCredentials();
|
||||
clearCookies();
|
||||
}
|
||||
|
||||
public void setCredentials(OwnCloudCredentials credentials) {
|
||||
if (credentials != null) {
|
||||
mCredentials = credentials;
|
||||
mCredentials.applyTo(this);
|
||||
} else {
|
||||
clearCredentials();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCredentials() {
|
||||
if (!(mCredentials instanceof OwnCloudAnonymousCredentials)) {
|
||||
mCredentials = OwnCloudCredentialsFactory.getAnonymousCredentials();
|
||||
}
|
||||
mCredentials.applyTo(this);
|
||||
}
|
||||
|
||||
public void applyCredentials() {
|
||||
mCredentials.applyTo(this);
|
||||
}
|
||||
|
||||
public int executeHttpMethod (HttpBaseMethod method) throws Exception {
|
||||
boolean repeatWithFreshCredentials;
|
||||
int repeatCounter = 0;
|
||||
int status;
|
||||
|
||||
do {
|
||||
setRequestId(method);
|
||||
|
||||
status = method.execute();
|
||||
checkFirstRedirection(method);
|
||||
|
||||
if(mFollowRedirects && !isIdPRedirection()) {
|
||||
status = followRedirection(method).getLastStatus();
|
||||
}
|
||||
|
||||
repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter);
|
||||
if (repeatWithFreshCredentials) {
|
||||
repeatCounter++;
|
||||
}
|
||||
} while (repeatWithFreshCredentials);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private void checkFirstRedirection(HttpBaseMethod method) {
|
||||
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||
if(location != null && !location.isEmpty()) {
|
||||
mRedirectedLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
private int executeRedirectedHttpMethod (HttpBaseMethod method) throws Exception {
|
||||
boolean repeatWithFreshCredentials;
|
||||
int repeatCounter = 0;
|
||||
int status;
|
||||
|
||||
do {
|
||||
setRequestId(method);
|
||||
|
||||
status = method.execute();
|
||||
|
||||
repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter);
|
||||
if (repeatWithFreshCredentials) {
|
||||
repeatCounter++;
|
||||
}
|
||||
} while (repeatWithFreshCredentials);
|
||||
|
||||
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);
|
||||
|
||||
Log_OC.d(TAG, "Executing " + method.getClass().getSimpleName() + " in request with id " + requestId);
|
||||
}
|
||||
|
||||
public RedirectionPath followRedirection(HttpBaseMethod method) throws Exception {
|
||||
int redirectionsCount = 0;
|
||||
int status = method.getStatusCode();
|
||||
RedirectionPath redirectionPath = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT);
|
||||
|
||||
while (redirectionsCount < MAX_REDIRECTIONS_COUNT &&
|
||||
(status == HttpConstants.HTTP_MOVED_PERMANENTLY ||
|
||||
status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
||||
status == HttpConstants.HTTP_TEMPORARY_REDIRECT)
|
||||
) {
|
||||
|
||||
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null
|
||||
? method.getResponseHeader(HttpConstants.LOCATION_HEADER)
|
||||
: method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||
|
||||
if (location != null) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Location to redirect: " + location);
|
||||
|
||||
redirectionPath.addLocation(location);
|
||||
|
||||
// Release the connection to avoid reach the max number of connections per host
|
||||
// due to it will be set a different url
|
||||
exhaustResponse(method.getResponseBodyAsStream());
|
||||
|
||||
method.setUrl(HttpUrl.parse(location));
|
||||
final String destination = method.getRequestHeader("Destination") != null
|
||||
? method.getRequestHeader("Destination")
|
||||
: method.getRequestHeader("destination");
|
||||
|
||||
if (destination != null) {
|
||||
final int suffixIndex = location.lastIndexOf(getUserFilesWebDavUri().toString());
|
||||
final String redirectionBase = location.substring(0, suffixIndex);
|
||||
final String destinationPath = destination.substring(mBaseUri.toString().length());
|
||||
|
||||
method.setRequestHeader("destination", redirectionBase + destinationPath);
|
||||
}
|
||||
try {
|
||||
status = executeRedirectedHttpMethod(method);
|
||||
} catch (HttpException e) {
|
||||
if(e.getMessage().contains(Integer.toString(HttpConstants.HTTP_MOVED_TEMPORARILY))) {
|
||||
status = HttpConstants.HTTP_MOVED_TEMPORARILY;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
redirectionPath.addStatus(status);
|
||||
redirectionsCount++;
|
||||
|
||||
} else {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No location to redirect!");
|
||||
status = HttpConstants.HTTP_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
return redirectionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
|
||||
*
|
||||
* @param responseBodyAsStream InputStream with the HTTP response to exhaust.
|
||||
*/
|
||||
public void exhaustResponse(InputStream responseBodyAsStream) {
|
||||
if (responseBodyAsStream != null) {
|
||||
try {
|
||||
while (responseBodyAsStream.read(sExhaustBuffer) >= 0) ;
|
||||
responseBodyAsStream.close();
|
||||
|
||||
} catch (IOException io) {
|
||||
Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response;" +
|
||||
" will be IGNORED", io);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Uri getBaseFilesWebDavUri(){
|
||||
return Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0);
|
||||
}
|
||||
|
||||
public Uri getUserFilesWebDavUri() {
|
||||
return mCredentials instanceof OwnCloudAnonymousCredentials
|
||||
? Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0)
|
||||
: Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId(
|
||||
mAccount.getSavedAccount(), getContext()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Uri getUploadsWebDavUri() {
|
||||
return mCredentials instanceof OwnCloudAnonymousCredentials
|
||||
? Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0)
|
||||
: Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0 + AccountUtils.getUserId(
|
||||
mAccount.getSavedAccount(), getContext()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root URI to the ownCloud server.
|
||||
*
|
||||
* Use with care.
|
||||
*
|
||||
* @param uri
|
||||
*/
|
||||
public void setBaseUri(Uri uri) {
|
||||
if (uri == null) {
|
||||
throw new IllegalArgumentException("URI cannot be NULL");
|
||||
}
|
||||
mBaseUri = uri;
|
||||
}
|
||||
|
||||
public Uri getBaseUri() {
|
||||
return mBaseUri;
|
||||
}
|
||||
|
||||
public final OwnCloudCredentials getCredentials() {
|
||||
return mCredentials;
|
||||
}
|
||||
|
||||
private void logCookie(Cookie cookie) {
|
||||
Log_OC.d(TAG, "Cookie name: " + cookie.name());
|
||||
Log_OC.d(TAG, " value: " + cookie.value());
|
||||
Log_OC.d(TAG, " domain: " + cookie.domain());
|
||||
Log_OC.d(TAG, " path: " + cookie.path());
|
||||
Log_OC.d(TAG, " expiryDate: " + cookie.expiresAt());
|
||||
Log_OC.d(TAG, " secure: " + cookie.secure());
|
||||
}
|
||||
|
||||
private void logCookiesAtRequest(Headers headers, String when) {
|
||||
int counter = 0;
|
||||
for (final String cookieHeader : headers.toMultimap().get("cookie")) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Cookies at request (" + when + ") (" + counter++ + "): "
|
||||
+ cookieHeader);
|
||||
}
|
||||
if (counter == 0) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No cookie at request before");
|
||||
}
|
||||
}
|
||||
|
||||
private void logSetCookiesAtResponse(Headers headers) {
|
||||
int counter = 0;
|
||||
for (final String cookieHeader : headers.toMultimap().get("set-cookie")) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||
"Set-Cookie (" + counter++ + "): " + cookieHeader);
|
||||
}
|
||||
if (counter == 0) {
|
||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No set-cookie");
|
||||
}
|
||||
}
|
||||
|
||||
public String getCookiesString() {
|
||||
String cookiesString = "";
|
||||
List<Cookie> cookieList = getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()));
|
||||
|
||||
if (cookieList != null) {
|
||||
for (Cookie cookie : cookieList) {
|
||||
cookiesString += cookie.toString() + ";";
|
||||
}
|
||||
}
|
||||
|
||||
return cookiesString;
|
||||
}
|
||||
|
||||
public void setCookiesForCurrentAccount(List<Cookie> cookies) {
|
||||
getOkHttpClient().cookieJar().saveFromResponse(
|
||||
HttpUrl.parse(getAccount().getBaseUri().toString()),
|
||||
cookies
|
||||
);
|
||||
}
|
||||
|
||||
public void setOwnCloudVersion(OwnCloudVersion version) {
|
||||
mVersion = version;
|
||||
}
|
||||
|
||||
public OwnCloudVersion getOwnCloudVersion() {
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
public void setAccount(OwnCloudAccount account) {
|
||||
this.mAccount = account;
|
||||
}
|
||||
|
||||
public OwnCloudAccount getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the status code of an execution and decides if should be repeated with fresh credentials.
|
||||
*
|
||||
* Invalidates current credentials if the request failed as anauthorized.
|
||||
*
|
||||
* Refresh current credentials if possible, and marks a retry.
|
||||
*
|
||||
* @param status
|
||||
* @param repeatCounter
|
||||
* @return
|
||||
*/
|
||||
private boolean checkUnauthorizedAccess(int status, int repeatCounter) {
|
||||
boolean credentialsWereRefreshed = false;
|
||||
|
||||
if (shouldInvalidateAccountCredentials(status)) {
|
||||
boolean invalidated = invalidateAccountCredentials();
|
||||
|
||||
if (invalidated) {
|
||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||
|
||||
try {
|
||||
mAccount.loadCredentials(getContext());
|
||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||
setCredentials(mAccount.getCredentials());
|
||||
credentialsWereRefreshed = true;
|
||||
|
||||
} catch (AccountsException | IOException e) {
|
||||
Log_OC.e(
|
||||
TAG,
|
||||
"Error while trying to refresh auth token for " + mAccount.getSavedAccount().name,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!credentialsWereRefreshed && mOwnCloudClientManager != null) {
|
||||
// if credentials are not refreshed, client must be removed
|
||||
// from the OwnCloudClientManager to prevent it is reused once and again
|
||||
mOwnCloudClientManager.removeClientFor(mAccount);
|
||||
}
|
||||
}
|
||||
// else: onExecute will finish with status 401
|
||||
}
|
||||
|
||||
return credentialsWereRefreshed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if credentials should be invalidated according the to the HTTPS status
|
||||
* of a network request just performed.
|
||||
*
|
||||
* @param httpStatusCode Result of the last request ran with the 'credentials' belows.
|
||||
|
||||
* @return 'True' if credentials should and might be invalidated, 'false' if shouldn't or
|
||||
* cannot be invalidated with the given arguments.
|
||||
*/
|
||||
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
||||
|
||||
boolean should = (httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED || isIdPRedirection()); // invalid credentials
|
||||
|
||||
should &= (mCredentials != null && // real credentials
|
||||
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
||||
|
||||
// test if have all the needed to effectively invalidate ...
|
||||
should &= (mAccount != null && mAccount.getSavedAccount() != null && getContext() != null);
|
||||
|
||||
return should;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates credentials stored for the given account in the system {@link AccountManager} and in
|
||||
* current {@link OwnCloudClientManagerFactory#getDefaultSingleton()} instance.
|
||||
*
|
||||
* {@link #shouldInvalidateAccountCredentials(int)} should be called first.
|
||||
*
|
||||
* @return 'True' if invalidation was successful, 'false' otherwise.
|
||||
*/
|
||||
private boolean invalidateAccountCredentials() {
|
||||
AccountManager am = AccountManager.get(getContext());
|
||||
am.invalidateAuthToken(
|
||||
mAccount.getSavedAccount().type,
|
||||
mCredentials.getAuthToken()
|
||||
);
|
||||
am.clearPassword(mAccount.getSavedAccount()); // being strict, only needed for Basic Auth credentials
|
||||
return true;
|
||||
}
|
||||
|
||||
public OwnCloudClientManager getOwnCloudClientManager() {
|
||||
return mOwnCloudClientManager;
|
||||
}
|
||||
|
||||
void setOwnCloudClientManager(OwnCloudClientManager clientManager) {
|
||||
mOwnCloudClientManager = clientManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the redirection is to an identity provider such as SAML or wayf
|
||||
* @return true if the redirection location includes SAML or wayf, false otherwise
|
||||
*/
|
||||
private boolean isIdPRedirection() {
|
||||
return (mRedirectedLocation != null &&
|
||||
(mRedirectedLocation.toUpperCase().contains("SAML") ||
|
||||
mRedirectedLocation.toLowerCase().contains("wayf")));
|
||||
}
|
||||
|
||||
public boolean followRedirects() {
|
||||
return mFollowRedirects;
|
||||
}
|
||||
|
||||
public void setFollowRedirects(boolean followRedirects) {
|
||||
this.mFollowRedirects = followRedirects;
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OwnCloudClientFactory {
|
||||
|
||||
final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Creates a OwnCloudClient setup for an ownCloud account
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param account The ownCloud account
|
||||
* @param appContext Android application context
|
||||
* @param currentActivity Caller {@link Activity}
|
||||
* @return A OwnCloudClient object ready to be used
|
||||
* @throws AuthenticatorException If the authenticator failed to get the authorization
|
||||
* token for the account.
|
||||
* @throws OperationCanceledException If the authenticator operation was cancelled while
|
||||
* getting the authorization token for the account.
|
||||
* @throws IOException If there was some I/O error while getting the
|
||||
* authorization token for the account.
|
||||
* @throws AccountNotFoundException If 'account' is unknown for the AccountManager
|
||||
*
|
||||
*/
|
||||
public static OwnCloudClient createOwnCloudClient (Account account, Context appContext,
|
||||
Activity currentActivity)
|
||||
throws OperationCanceledException, AuthenticatorException, IOException,
|
||||
AccountNotFoundException {
|
||||
Uri baseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(appContext, account));
|
||||
AccountManager am = AccountManager.get(appContext);
|
||||
// TODO avoid calling to getUserData here
|
||||
boolean isOauth2 =
|
||||
am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2) != null;
|
||||
boolean isSamlSso =
|
||||
am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null;
|
||||
OwnCloudClient client = createOwnCloudClient(baseUri, appContext, !isSamlSso);
|
||||
|
||||
String username = AccountUtils.getUsernameForAccount(account);
|
||||
if (isOauth2) { // TODO avoid a call to getUserData here
|
||||
AccountManagerFuture<Bundle> future = am.getAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
|
||||
null,
|
||||
currentActivity,
|
||||
null,
|
||||
null);
|
||||
|
||||
Bundle result = future.getResult();
|
||||
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
if (accessToken == null) throw new AuthenticatorException("WTF!");
|
||||
client.setCredentials(
|
||||
OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken)
|
||||
);
|
||||
|
||||
} else if (isSamlSso) { // TODO avoid a call to getUserData here
|
||||
AccountManagerFuture<Bundle> future = am.getAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
|
||||
null,
|
||||
currentActivity,
|
||||
null,
|
||||
null);
|
||||
|
||||
Bundle result = future.getResult();
|
||||
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
if (accessToken == null) throw new AuthenticatorException("WTF!");
|
||||
client.setCredentials(
|
||||
OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken)
|
||||
);
|
||||
|
||||
|
||||
} else {
|
||||
AccountManagerFuture<Bundle> future = am.getAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypePass(account.type),
|
||||
null,
|
||||
currentActivity,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
Bundle result = future.getResult();
|
||||
String password = result.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
OwnCloudVersion version = AccountUtils.getServerVersionForAccount(account, appContext);
|
||||
client.setCredentials(
|
||||
OwnCloudCredentialsFactory.newBasicCredentials(
|
||||
username,
|
||||
password,
|
||||
(version != null && version.isPreemptiveAuthenticationPreferred())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Restore cookies
|
||||
AccountUtils.restoreCookies(account, client, appContext);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a OwnCloudClient to access a URL and sets the desired parameters for ownCloud
|
||||
* client connections.
|
||||
*
|
||||
* @param uri URL to the ownCloud server; BASE ENTRY POINT, not WebDavPATH
|
||||
* @param context Android context where the OwnCloudClient is being created.
|
||||
* @return A OwnCloudClient object ready to be used
|
||||
*/
|
||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
||||
boolean followRedirects) {
|
||||
OwnCloudClient client = new OwnCloudClient(uri);
|
||||
|
||||
client.setFollowRedirects(followRedirects);
|
||||
|
||||
client.setContext(context);
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||
|
||||
/**
|
||||
* Manager to create and reuse OwnCloudClient instances to access remote OC servers.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
|
||||
public interface OwnCloudClientManager {
|
||||
|
||||
OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException,
|
||||
OperationCanceledException, AuthenticatorException,
|
||||
IOException;
|
||||
|
||||
OwnCloudClient removeClientFor(OwnCloudAccount account);
|
||||
|
||||
void saveAllClients(Context context, String accountType)
|
||||
throws AccountNotFoundException, AuthenticatorException,
|
||||
IOException, OperationCanceledException;
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
public class OwnCloudClientManagerFactory {
|
||||
|
||||
public static enum Policy {
|
||||
ALWAYS_NEW_CLIENT,
|
||||
SINGLE_SESSION_PER_ACCOUNT,
|
||||
SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING
|
||||
}
|
||||
|
||||
private static Policy sDefaultPolicy = Policy.ALWAYS_NEW_CLIENT;
|
||||
|
||||
private static OwnCloudClientManager sDefaultSingleton;
|
||||
|
||||
private static String sUserAgent;
|
||||
|
||||
public static OwnCloudClientManager newDefaultOwnCloudClientManager() {
|
||||
return newOwnCloudClientManager(sDefaultPolicy);
|
||||
}
|
||||
|
||||
public static OwnCloudClientManager newOwnCloudClientManager(Policy policy) {
|
||||
switch (policy) {
|
||||
case ALWAYS_NEW_CLIENT:
|
||||
return new SimpleFactoryManager();
|
||||
|
||||
case SINGLE_SESSION_PER_ACCOUNT:
|
||||
return new SingleSessionManager();
|
||||
|
||||
case SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING:
|
||||
return new DynamicSessionManager();
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown policy");
|
||||
}
|
||||
}
|
||||
|
||||
public static OwnCloudClientManager getDefaultSingleton() {
|
||||
if (sDefaultSingleton == null) {
|
||||
sDefaultSingleton = newDefaultOwnCloudClientManager();
|
||||
}
|
||||
return sDefaultSingleton;
|
||||
}
|
||||
|
||||
public static Policy getDefaultPolicy() {
|
||||
return sDefaultPolicy;
|
||||
}
|
||||
|
||||
public static void setDefaultPolicy(Policy policy) {
|
||||
if (policy == null) {
|
||||
throw new IllegalArgumentException("Default policy cannot be NULL");
|
||||
}
|
||||
if (defaultSingletonMustBeUpdated(policy)) {
|
||||
sDefaultSingleton = null;
|
||||
}
|
||||
sDefaultPolicy = policy;
|
||||
}
|
||||
|
||||
public static void setUserAgent(String userAgent) {
|
||||
sUserAgent = userAgent;
|
||||
}
|
||||
|
||||
public static String getUserAgent() {
|
||||
return sUserAgent;
|
||||
}
|
||||
|
||||
private static boolean defaultSingletonMustBeUpdated(Policy policy) {
|
||||
if (sDefaultSingleton == null) {
|
||||
return false;
|
||||
}
|
||||
if (policy == Policy.ALWAYS_NEW_CLIENT &&
|
||||
!(sDefaultSingleton instanceof SimpleFactoryManager)) {
|
||||
return true;
|
||||
}
|
||||
if (policy == Policy.SINGLE_SESSION_PER_ACCOUNT &&
|
||||
!(sDefaultSingleton instanceof SingleSessionManager)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SimpleFactoryManager implements OwnCloudClientManager {
|
||||
|
||||
private static final String TAG = SimpleFactoryManager.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws
|
||||
OperationCanceledException, AuthenticatorException, IOException {
|
||||
|
||||
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
|
||||
|
||||
OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(
|
||||
account.getBaseUri(),
|
||||
context.getApplicationContext(),
|
||||
true);
|
||||
|
||||
Log_OC.v(TAG, " new client {" +
|
||||
(account.getName() != null ?
|
||||
account.getName() :
|
||||
AccountUtils.buildAccountName(account.getBaseUri(), "")
|
||||
|
||||
) + ", " + client.hashCode() + "}");
|
||||
|
||||
if (account.getCredentials() == null) {
|
||||
account.loadCredentials(context);
|
||||
}
|
||||
client.setCredentials(account.getCredentials());
|
||||
client.setAccount(account);
|
||||
client.setContext(context);
|
||||
client.setOwnCloudClientManager(this);
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
// nothing to do - not taking care of tracking instances!
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
// nothing to do - not taking care of tracking instances!
|
||||
}
|
||||
|
||||
}
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudSamlSsoCredentials;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Implementation of {@link OwnCloudClientManager}
|
||||
*
|
||||
* TODO check multithreading safety
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author Christian Schabesberger
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class SingleSessionManager implements OwnCloudClientManager {
|
||||
|
||||
private static final String TAG = SingleSessionManager.class.getSimpleName();
|
||||
|
||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
|
||||
AuthenticatorException, IOException {
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "getClientFor starting ");
|
||||
}
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account");
|
||||
}
|
||||
|
||||
OwnCloudClient client = null;
|
||||
String accountName = account.getName();
|
||||
String sessionName = account.getCredentials() == null ? "" :
|
||||
AccountUtils.buildAccountName(
|
||||
account.getBaseUri(),
|
||||
account.getCredentials().getAuthToken());
|
||||
|
||||
if (accountName != null) {
|
||||
client = mClientsWithKnownUsername.get(accountName);
|
||||
}
|
||||
boolean reusingKnown = false; // just for logs
|
||||
if (client == null) {
|
||||
if (accountName != null) {
|
||||
client = mClientsWithUnknownUsername.remove(sessionName);
|
||||
if (client != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
||||
}
|
||||
mClientsWithKnownUsername.put(accountName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "moved client to account " + accountName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client = mClientsWithUnknownUsername.get(sessionName);
|
||||
}
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for account " + accountName);
|
||||
}
|
||||
reusingKnown = true;
|
||||
}
|
||||
|
||||
if (client == null) {
|
||||
// no client to reuse - create a new one
|
||||
client = OwnCloudClientFactory.createOwnCloudClient(
|
||||
account.getBaseUri(),
|
||||
context.getApplicationContext(),
|
||||
true); // TODO remove dependency on OwnCloudClientFactory
|
||||
client.setAccount(account);
|
||||
client.setContext(context);
|
||||
client.setOwnCloudClientManager(this);
|
||||
|
||||
account.loadCredentials(context);
|
||||
client.setCredentials(account.getCredentials());
|
||||
|
||||
if (client.getCredentials() instanceof OwnCloudSamlSsoCredentials) {
|
||||
client.disableAutomaticCookiesHandling();
|
||||
}
|
||||
|
||||
if (accountName != null) {
|
||||
mClientsWithKnownUsername.put(accountName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "new client for account " + accountName);
|
||||
}
|
||||
|
||||
} else {
|
||||
mClientsWithUnknownUsername.put(sessionName, client);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "new client for session " + sessionName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!reusingKnown && Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
||||
}
|
||||
|
||||
keepCredentialsUpdated(client);
|
||||
keepCookiesUpdated(context, account, client);
|
||||
keepUriUpdated(account, client);
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "getClientFor finishing ");
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "removeClientFor starting ");
|
||||
}
|
||||
|
||||
if (account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
OwnCloudClient client;
|
||||
String accountName = account.getName();
|
||||
if (accountName != null) {
|
||||
client = mClientsWithKnownUsername.remove(accountName);
|
||||
if (client != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "Removed client for account " + accountName);
|
||||
}
|
||||
return client;
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log_OC.v(TAG, "No client tracked for account " + accountName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mClientsWithUnknownUsername.clear();
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "removeClientFor finishing ");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void saveAllClients(Context context, String accountType) {
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "Saving sessions... ");
|
||||
}
|
||||
|
||||
Iterator<String> accountNames = mClientsWithKnownUsername.keySet().iterator();
|
||||
String accountName;
|
||||
Account account;
|
||||
while (accountNames.hasNext()) {
|
||||
accountName = accountNames.next();
|
||||
account = new Account(accountName, accountType);
|
||||
AccountUtils.saveClient(
|
||||
mClientsWithKnownUsername.get(accountName),
|
||||
account,
|
||||
context);
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log_OC.d(TAG, "All sessions saved");
|
||||
}
|
||||
}
|
||||
|
||||
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
|
||||
reusedClient.applyCredentials();
|
||||
}
|
||||
|
||||
private void keepCookiesUpdated(Context context, OwnCloudAccount account, OwnCloudClient reusedClient) {
|
||||
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||
if (am != null && account.getSavedAccount() != null) {
|
||||
String recentCookies = am.getUserData(account.getSavedAccount(), AccountUtils.Constants.KEY_COOKIES);
|
||||
String previousCookies = reusedClient.getCookiesString();
|
||||
if (recentCookies != null && previousCookies != "" && !recentCookies.equals(previousCookies)) {
|
||||
AccountUtils.restoreCookies(account.getSavedAccount(), reusedClient, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
private void keepUriUpdated(OwnCloudAccount account, OwnCloudClient reusedClient) {
|
||||
Uri recentUri = account.getBaseUri();
|
||||
if (!recentUri.equals(reusedClient.getBaseUri())) {
|
||||
reusedClient.setBaseUri(recentUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.accounts;
|
||||
|
||||
/**
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class AccountTypeUtils {
|
||||
|
||||
public static String getAuthTokenTypePass(String accountType) {
|
||||
return accountType + ".password";
|
||||
}
|
||||
|
||||
public static String getAuthTokenTypeAccessToken(String accountType) {
|
||||
return accountType + ".oauth2.access_token";
|
||||
}
|
||||
|
||||
public static String getAuthTokenTypeRefreshToken(String accountType) {
|
||||
return accountType + ".oauth2.refresh_token";
|
||||
}
|
||||
|
||||
public static String getAuthTokenTypeSamlSessionCookie(String accountType) {
|
||||
return accountType + ".saml.web_sso.session_cookie";
|
||||
}
|
||||
|
||||
}
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* 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.accounts;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountsException;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
|
||||
public class AccountUtils {
|
||||
|
||||
private static final String TAG = AccountUtils.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Constructs full url to host and webdav resource basing on host version
|
||||
*
|
||||
* @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
|
||||
* @param account A stored ownCloud {@link Account}
|
||||
* @return Full URL to WebDAV endpoint in the server corresponding to 'account'.
|
||||
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager
|
||||
*/
|
||||
public static String getWebDavUrlForAccount(Context context, Account account)
|
||||
throws AccountNotFoundException {
|
||||
String webDavUrlForAccount = "";
|
||||
|
||||
try {
|
||||
OwnCloudCredentials ownCloudCredentials = getCredentialsForAccount(context, account);
|
||||
webDavUrlForAccount = getBaseUrlForAccount(context, account) + OwnCloudClient.WEBDAV_FILES_PATH_4_0
|
||||
+ ownCloudCredentials.getUsername();
|
||||
} catch (OperationCanceledException e) {
|
||||
e.printStackTrace();
|
||||
} catch (AuthenticatorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return webDavUrlForAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts url server from the account
|
||||
*
|
||||
* @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
|
||||
* @param account A stored ownCloud {@link Account}
|
||||
* @return Full URL to the server corresponding to 'account', ending in the base path
|
||||
* common to all API endpoints.
|
||||
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager
|
||||
*/
|
||||
public static String getBaseUrlForAccount(Context context, Account account)
|
||||
throws AccountNotFoundException {
|
||||
AccountManager ama = AccountManager.get(context.getApplicationContext());
|
||||
String baseurl = ama.getUserData(account, Constants.KEY_OC_BASE_URL);
|
||||
|
||||
if (baseurl == null)
|
||||
throw new AccountNotFoundException(account, "Account not found", null);
|
||||
|
||||
return baseurl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the username corresponding to an OC account.
|
||||
*
|
||||
* @param account An OC account
|
||||
* @return Username for the given account, extracted from the account.name
|
||||
*/
|
||||
public static String getUsernameForAccount(Account account) {
|
||||
String username = null;
|
||||
try {
|
||||
username = account.name.substring(0, account.name.lastIndexOf('@'));
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Couldn't get a username for the given account", e);
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored server version corresponding to an OC account.
|
||||
*
|
||||
* @param account An OC account
|
||||
* @param context Application context
|
||||
* @return Version of the OC server, according to last check
|
||||
*/
|
||||
public static OwnCloudVersion getServerVersionForAccount(Account account, Context context) {
|
||||
AccountManager ama = AccountManager.get(context);
|
||||
OwnCloudVersion version = null;
|
||||
try {
|
||||
String versionString = ama.getUserData(account, Constants.KEY_OC_VERSION);
|
||||
version = new OwnCloudVersion(versionString);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Couldn't get a the server version for an account", e);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws AuthenticatorException
|
||||
* @throws OperationCanceledException
|
||||
*/
|
||||
public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account)
|
||||
throws OperationCanceledException, AuthenticatorException, IOException {
|
||||
|
||||
OwnCloudCredentials credentials;
|
||||
AccountManager am = AccountManager.get(context);
|
||||
|
||||
String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
||||
boolean isOauth2 = supportsOAuth2 != null && supportsOAuth2.equals("TRUE");
|
||||
|
||||
String supportsSamlSSo = am.getUserData(account,
|
||||
AccountUtils.Constants.KEY_SUPPORTS_SAML_WEB_SSO);
|
||||
|
||||
boolean isSamlSso = supportsSamlSSo != null && supportsSamlSSo.equals("TRUE");
|
||||
|
||||
String username = AccountUtils.getUsernameForAccount(account);
|
||||
OwnCloudVersion version = new OwnCloudVersion(am.getUserData(account, Constants.KEY_OC_VERSION));
|
||||
|
||||
if (isOauth2) {
|
||||
String accessToken = am.blockingGetAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
|
||||
false);
|
||||
|
||||
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
|
||||
|
||||
} else if (isSamlSso) {
|
||||
String accessToken = am.blockingGetAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
|
||||
false);
|
||||
|
||||
credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken);
|
||||
|
||||
} else {
|
||||
String password = am.blockingGetAuthToken(
|
||||
account,
|
||||
AccountTypeUtils.getAuthTokenTypePass(account.type),
|
||||
false);
|
||||
|
||||
credentials = OwnCloudCredentialsFactory.newBasicCredentials(
|
||||
username,
|
||||
password,
|
||||
version.isPreemptiveAuthenticationPreferred()
|
||||
);
|
||||
}
|
||||
|
||||
return credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user id corresponding to an OC account.
|
||||
* @param account ownCloud account
|
||||
* @return user id
|
||||
*/
|
||||
public static String getUserId(Account account, Context context) {
|
||||
AccountManager accountMgr = AccountManager.get(context);
|
||||
return accountMgr.getUserData(account, Constants.KEY_ID);
|
||||
}
|
||||
|
||||
public static String buildAccountNameOld(Uri serverBaseUrl, String username) {
|
||||
if (serverBaseUrl.getScheme() == null) {
|
||||
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
||||
}
|
||||
String accountName = username + "@" + serverBaseUrl.getHost();
|
||||
if (serverBaseUrl.getPort() >= 0) {
|
||||
accountName += ":" + serverBaseUrl.getPort();
|
||||
}
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public static String buildAccountName(Uri serverBaseUrl, String username) {
|
||||
if (serverBaseUrl.getScheme() == null) {
|
||||
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
||||
}
|
||||
|
||||
// Remove http:// or https://
|
||||
String url = serverBaseUrl.toString();
|
||||
if (url.contains("://")) {
|
||||
url = url.substring(serverBaseUrl.toString().indexOf("://") + 3);
|
||||
}
|
||||
String accountName = username + "@" + url;
|
||||
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
||||
// Account Manager
|
||||
AccountManager ac = AccountManager.get(context.getApplicationContext());
|
||||
|
||||
if (client != null) {
|
||||
String cookiesString = client.getCookiesString();
|
||||
if (!"".equals(cookiesString)) {
|
||||
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
|
||||
Log_OC.d(TAG, "Saving Cookies: "+ cookiesString );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the client cookies persisted in an account stored in the system AccountManager.
|
||||
*
|
||||
* @param account Stored account.
|
||||
* @param client Client to restore cookies in.
|
||||
* @param context Android context used to access the system AccountManager.
|
||||
*/
|
||||
public static void restoreCookies(Account account, OwnCloudClient client, Context context) {
|
||||
if (account == null) {
|
||||
Log_OC.d(TAG, "Cannot restore cookie for null account");
|
||||
|
||||
} else {
|
||||
Log_OC.d(TAG, "Restoring cookies for " + account.name);
|
||||
|
||||
// Account Manager
|
||||
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||
|
||||
Uri serverUri = (client.getBaseUri() != null) ? client.getBaseUri() : client.getUserFilesWebDavUri();
|
||||
|
||||
String cookiesString = am.getUserData(account, Constants.KEY_COOKIES);
|
||||
if (cookiesString != null) {
|
||||
String[] rawCookies = cookiesString.split(";");
|
||||
List<Cookie> cookieList = new ArrayList<>(rawCookies.length);
|
||||
for(String rawCookie : rawCookies) {
|
||||
rawCookie = rawCookie.replace(" ", "");
|
||||
final int equalPos = rawCookie.indexOf('=');
|
||||
if (equalPos == -1) continue;
|
||||
cookieList.add(new Cookie.Builder()
|
||||
.name(rawCookie.substring(0, equalPos))
|
||||
.value(rawCookie.substring(equalPos + 1))
|
||||
.domain(serverUri.getHost())
|
||||
.path(
|
||||
serverUri.getPath().equals("")
|
||||
? FileUtils.PATH_SEPARATOR
|
||||
: serverUri.getPath()
|
||||
)
|
||||
.build());
|
||||
}
|
||||
client.setCookiesForCurrentAccount(cookieList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccountNotFoundException extends AccountsException {
|
||||
|
||||
/**
|
||||
* Generated - should be refreshed every time the class changes!!
|
||||
*/
|
||||
private static final long serialVersionUID = -1684392454798508693L;
|
||||
|
||||
private Account mFailedAccount;
|
||||
|
||||
public AccountNotFoundException(Account failedAccount, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
mFailedAccount = failedAccount;
|
||||
}
|
||||
|
||||
public Account getFailedAccount() {
|
||||
return mFailedAccount;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Constants {
|
||||
/**
|
||||
* Version should be 3 numbers separated by dot so it can be parsed by
|
||||
* {@link OwnCloudVersion}
|
||||
*/
|
||||
public static final String KEY_OC_VERSION = "oc_version";
|
||||
/**
|
||||
* Base url should point to owncloud installation without trailing / ie:
|
||||
* http://server/path or https://owncloud.server
|
||||
*/
|
||||
public static final String KEY_OC_BASE_URL = "oc_base_url";
|
||||
/**
|
||||
* Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
|
||||
*/
|
||||
public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
|
||||
/**
|
||||
* Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
|
||||
*/
|
||||
public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
|
||||
/**
|
||||
* OC account cookies
|
||||
*/
|
||||
public static final String KEY_COOKIES = "oc_account_cookies";
|
||||
|
||||
/**
|
||||
* OC account version
|
||||
*/
|
||||
public static final String KEY_OC_ACCOUNT_VERSION = "oc_account_version";
|
||||
|
||||
/**
|
||||
* User's id
|
||||
*/
|
||||
public static final String KEY_ID = "oc_id";
|
||||
|
||||
/**
|
||||
* User's display name
|
||||
*/
|
||||
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
||||
|
||||
/**
|
||||
* OAuth2 refresh token
|
||||
**/
|
||||
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
||||
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.authentication;
|
||||
|
||||
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;
|
||||
|
||||
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
||||
|
||||
private static final String TAG = OwnCloudCredentials.class.getSimpleName();
|
||||
|
||||
private String mUsername;
|
||||
private String mPassword;
|
||||
|
||||
public OwnCloudBasicCredentials(String username, String password) {
|
||||
mUsername = username != null ? username : "";
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return mUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthToken() {
|
||||
return mPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenExpires() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenCanBeRefreshed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.authentication;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
|
||||
public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
||||
|
||||
private String mUsername;
|
||||
private String mAccessToken;
|
||||
|
||||
public OwnCloudBearerCredentials(String username, String accessToken) {
|
||||
mUsername = username != null ? username : "";
|
||||
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
|
||||
public String getUsername() {
|
||||
// not relevant for authentication, but relevant for informational purposes
|
||||
return mUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthToken() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenExpires() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenCanBeRefreshed() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
|
||||
public interface OwnCloudCredentials {
|
||||
|
||||
void applyTo(OwnCloudClient ownCloudClient);
|
||||
|
||||
String getUsername();
|
||||
|
||||
String getAuthToken();
|
||||
|
||||
boolean authTokenExpires();
|
||||
|
||||
boolean authTokenCanBeRefreshed();
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
|
||||
public class OwnCloudCredentialsFactory {
|
||||
|
||||
public static final String CREDENTIAL_CHARSET = "UTF-8";
|
||||
|
||||
private static OwnCloudAnonymousCredentials sAnonymousCredentials;
|
||||
|
||||
public static OwnCloudCredentials newBasicCredentials(String username, String password) {
|
||||
return new OwnCloudBasicCredentials(username, password);
|
||||
}
|
||||
|
||||
public static OwnCloudCredentials newBasicCredentials(
|
||||
String username, String password, boolean preemptiveMode
|
||||
) {
|
||||
return new OwnCloudBasicCredentials(username, password, preemptiveMode);
|
||||
}
|
||||
|
||||
public static OwnCloudCredentials newBearerCredentials(String username, String authToken) {
|
||||
return new OwnCloudBearerCredentials(username, authToken);
|
||||
}
|
||||
|
||||
public static OwnCloudCredentials newSamlSsoCredentials(String username, String sessionCookie) {
|
||||
return new OwnCloudSamlSsoCredentials(username, sessionCookie);
|
||||
}
|
||||
|
||||
public static final OwnCloudCredentials getAnonymousCredentials() {
|
||||
if (sAnonymousCredentials == null) {
|
||||
sAnonymousCredentials = new OwnCloudAnonymousCredentials();
|
||||
}
|
||||
return sAnonymousCredentials;
|
||||
}
|
||||
|
||||
public static final class OwnCloudAnonymousCredentials implements OwnCloudCredentials {
|
||||
|
||||
protected OwnCloudAnonymousCredentials() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(OwnCloudClient client) {
|
||||
// Clear previous basic credentials
|
||||
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthToken() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenExpires() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenCanBeRefreshed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
// no user name
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.authentication;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
|
||||
public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
||||
|
||||
private String mUsername;
|
||||
private String mSessionCookie;
|
||||
|
||||
public OwnCloudSamlSsoCredentials(String username, String sessionCookie) {
|
||||
mUsername = username != null ? username : "";
|
||||
mSessionCookie = sessionCookie != null ? sessionCookie : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(OwnCloudClient client) {
|
||||
// Clear previous credentials
|
||||
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||
|
||||
HttpClient.addHeaderForAllRequests(HttpConstants.COOKIE_HEADER, mSessionCookie);
|
||||
client.setFollowRedirects(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
// not relevant for authentication, but relevant for informational purposes
|
||||
return mUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthToken() {
|
||||
return mSessionCookie;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenExpires() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authTokenCanBeRefreshed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
/**
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
public class BearerCredentials {
|
||||
|
||||
public static final int HASH_SEED = 17;
|
||||
public static final int HASH_OFFSET = 37;
|
||||
|
||||
private String mAccessToken;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor with the bearer token
|
||||
*
|
||||
* @param token The bearer token
|
||||
*/
|
||||
public BearerCredentials(String token) {
|
||||
/*if (token == null) {
|
||||
throw new IllegalArgumentException("Bearer token may not be null");
|
||||
}*/
|
||||
mAccessToken = (token == null) ? "" : token;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the access token
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String getAccessToken() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get this object string.
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String toString() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a hash of the access token.
|
||||
*
|
||||
* @return The hash code of the access token
|
||||
*/
|
||||
public int hashCode() {
|
||||
return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* These credentials are assumed equal if accessToken is the same.
|
||||
*
|
||||
* @param o The other object to compare with.
|
||||
*
|
||||
* @return 'True' if the object is equivalent.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (this == o) return true;
|
||||
if (this.getClass().equals(o.getClass())) {
|
||||
BearerCredentials that = (BearerCredentials) o;
|
||||
if (mAccessToken.equals(that.mAccessToken)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public class OAuth2ClientConfiguration {
|
||||
|
||||
private String mClientId;
|
||||
|
||||
private String mClientSecret;
|
||||
|
||||
private String mRedirectUri;
|
||||
|
||||
public OAuth2ClientConfiguration(String clientId, String clientSecret, String redirectUri) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return mClientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return mClientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
return mRedirectUri;
|
||||
}
|
||||
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
this.mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
/**
|
||||
* Constant values for OAuth 2 protocol.
|
||||
*
|
||||
* Includes required and optional parameter NAMES used in the 'authorization code' grant type.
|
||||
*/
|
||||
|
||||
public class OAuth2Constants {
|
||||
|
||||
/// Parameters to send to the Authorization Endpoint
|
||||
public static final String KEY_RESPONSE_TYPE = "response_type";
|
||||
public static final String KEY_REDIRECT_URI = "redirect_uri";
|
||||
public static final String KEY_CLIENT_ID = "client_id";
|
||||
public static final String KEY_SCOPE = "scope";
|
||||
public static final String KEY_STATE = "state";
|
||||
|
||||
/// Additional parameters to send to the Token Endpoint
|
||||
public static final String KEY_GRANT_TYPE = "grant_type";
|
||||
public static final String KEY_CODE = "code";
|
||||
|
||||
// Used to get the Access Token using Refresh Token
|
||||
public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
|
||||
|
||||
/// Parameters received in an OK response from the Token Endpoint
|
||||
public static final String KEY_ACCESS_TOKEN = "access_token";
|
||||
public static final String KEY_TOKEN_TYPE = "token_type";
|
||||
public static final String KEY_EXPIRES_IN = "expires_in";
|
||||
public static final String KEY_REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
/// Parameters in an ERROR response
|
||||
public static final String KEY_ERROR = "error";
|
||||
public static final String KEY_ERROR_DESCRIPTION = "error_description";
|
||||
public static final String KEY_ERROR_URI = "error_uri";
|
||||
public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
|
||||
|
||||
/// Extra not standard
|
||||
public static final String KEY_USER_ID = "user_id";
|
||||
|
||||
/// Depends on oauth2 grant type
|
||||
public static final String OAUTH2_RESPONSE_TYPE_CODE = "code";
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
|
||||
public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private String mGrantType;
|
||||
private String mCode;
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRedirectUri;
|
||||
private final String mAccessTokenEndpointPath;
|
||||
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
|
||||
|
||||
public OAuth2GetAccessTokenOperation(
|
||||
String grantType,
|
||||
String code,
|
||||
String clientId,
|
||||
String secretId,
|
||||
String redirectUri,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRedirectUri = redirectUri;
|
||||
mGrantType = grantType;
|
||||
mCode = code;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult<Map<String, String>> result = null;
|
||||
|
||||
try {
|
||||
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE, mGrantType)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CODE, mCode)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
OwnCloudCredentials oauthCredentials =
|
||||
new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
String response = postMethod.getResponseBodyAsString();
|
||||
if (response != null && response.length() > 0) {
|
||||
JSONObject tokenJson = new JSONObject(response);
|
||||
Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||
result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR);
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public enum OAuth2GrantType {
|
||||
AUTHORIZATION_CODE("authorization_code"),
|
||||
IMPLICIT("implicit"),
|
||||
PASSWORD("password"),
|
||||
CLIENT_CREDENTIAL("client_credentials"),
|
||||
REFRESH_TOKEN("refresh_token") // not a grant type conceptually, but used as such to refresh access tokens
|
||||
;
|
||||
|
||||
private String mValue;
|
||||
|
||||
OAuth2GrantType(String value) {
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public interface OAuth2Provider {
|
||||
|
||||
/**
|
||||
* {@link OAuth2RequestBuilder} implementation for this provider.
|
||||
*
|
||||
* @return {@link OAuth2RequestBuilder} implementation.
|
||||
*/
|
||||
OAuth2RequestBuilder getOperationBuilder();
|
||||
|
||||
|
||||
/**
|
||||
* Set configuration of the client that will use this {@link OAuth2Provider}
|
||||
* @param oAuth2ClientConfiguration Configuration of the client that will use this {@link OAuth2Provider}
|
||||
*/
|
||||
void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration);
|
||||
|
||||
/**
|
||||
* Configuration of the client that is using this {@link OAuth2Provider}
|
||||
* return Configuration of the client that is usinng this {@link OAuth2Provider}
|
||||
*/
|
||||
OAuth2ClientConfiguration getClientConfiguration();
|
||||
|
||||
|
||||
/**
|
||||
* Set base URI to authorization server.
|
||||
*
|
||||
* @param authorizationServerUri Set base URL to authorization server.
|
||||
*/
|
||||
void setAuthorizationServerUri(String authorizationServerUri);
|
||||
|
||||
/**
|
||||
* base URI to authorization server.
|
||||
*
|
||||
* @return Base URL to authorization server.
|
||||
*/
|
||||
String getAuthorizationServerUri();
|
||||
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2ProvidersRegistry {
|
||||
|
||||
private Map<String, OAuth2Provider> mProviders = new HashMap<>();
|
||||
|
||||
private OAuth2Provider mDefaultProvider = null;
|
||||
|
||||
private OAuth2ProvidersRegistry () {
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
|
||||
*/
|
||||
private static class LazyHolder {
|
||||
private static final OAuth2ProvidersRegistry INSTANCE = new OAuth2ProvidersRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton accesor.
|
||||
*
|
||||
* @return Singleton isntance of {@link OAuth2ProvidersRegistry}
|
||||
*/
|
||||
public static OAuth2ProvidersRegistry getInstance() {
|
||||
return LazyHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@link OAuth2Provider} with the name passed as parameter.
|
||||
*
|
||||
* @param name Name to bind 'oAuthProvider' in the registry.
|
||||
* @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry.
|
||||
* @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null.
|
||||
*/
|
||||
public void registerProvider(String name, OAuth2Provider oAuth2Provider) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name must not be NULL");
|
||||
}
|
||||
if (oAuth2Provider == null) {
|
||||
throw new IllegalArgumentException("oAuth2Provider must not be NULL");
|
||||
}
|
||||
|
||||
mProviders.put(name, oAuth2Provider);
|
||||
if (mProviders.size() == 1) {
|
||||
mDefaultProvider = oAuth2Provider;
|
||||
}
|
||||
}
|
||||
|
||||
public OAuth2Provider unregisterProvider(String name) {
|
||||
OAuth2Provider unregisteredProvider = mProviders.remove(name);
|
||||
if (mProviders.size() == 0) {
|
||||
mDefaultProvider = null;
|
||||
} else if (unregisteredProvider != null && unregisteredProvider == mDefaultProvider) {
|
||||
mDefaultProvider = mProviders.values().iterator().next();
|
||||
}
|
||||
return unregisteredProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default {@link OAuth2Provider}.
|
||||
*
|
||||
* @return Default provider, or NULL if there is no provider.
|
||||
*/
|
||||
public OAuth2Provider getProvider() {
|
||||
return mDefaultProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link OAuth2Provider} registered with the name passed as parameter.
|
||||
*
|
||||
* @param name Name used to register the desired {@link OAuth2Provider}
|
||||
* @return {@link OAuth2Provider} registered with the name 'name'
|
||||
*/
|
||||
public OAuth2Provider getProvider(String name) {
|
||||
return mProviders.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2Provider} registered with the name passed as parameter as the default provider
|
||||
*
|
||||
* @param name Name used to register the {@link OAuth2Provider} to set as default.
|
||||
* @return {@link OAuth2Provider} set as default, or NULL if no provider was registered with 'name'.
|
||||
*/
|
||||
public OAuth2Provider setDefaultProvider(String name) {
|
||||
OAuth2Provider toDefault = mProviders.get(name);
|
||||
if (toDefault != null) {
|
||||
mDefaultProvider = toDefault;
|
||||
}
|
||||
return toDefault;
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class OAuth2QueryParser {
|
||||
|
||||
private static final String TAG = OAuth2QueryParser.class.getName();
|
||||
|
||||
private Map<String, String> mOAuth2ParsedAuthorizationResponse;
|
||||
|
||||
public OAuth2QueryParser() {
|
||||
mOAuth2ParsedAuthorizationResponse = new HashMap<>();
|
||||
}
|
||||
|
||||
public Map<String, String> parse(String query) {
|
||||
mOAuth2ParsedAuthorizationResponse.clear();
|
||||
|
||||
if (query != null) {
|
||||
String[] pairs = query.split("&");
|
||||
int i = 0;
|
||||
String key = "";
|
||||
String value;
|
||||
while (pairs.length > i) {
|
||||
int j = 0;
|
||||
String[] part = pairs[i].split("=");
|
||||
while (part.length > j) {
|
||||
String p = part[j];
|
||||
if (j == 0) {
|
||||
key = p;
|
||||
} else if (j == 1) {
|
||||
value = p;
|
||||
mOAuth2ParsedAuthorizationResponse.put(key, value);
|
||||
}
|
||||
|
||||
Log_OC.v(TAG, "[" + i + "," + j + "] = " + p);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return mOAuth2ParsedAuthorizationResponse;
|
||||
}
|
||||
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David González Verdugo
|
||||
* @author Christian Schabesberger
|
||||
*
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
|
||||
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRefreshToken;
|
||||
|
||||
private final String mAccessTokenEndpointPath;
|
||||
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
|
||||
public OAuth2RefreshAccessTokenOperation(
|
||||
String clientId,
|
||||
String secretId,
|
||||
String refreshToken,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRefreshToken = refreshToken;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<Map<String, String>> run(OwnCloudClient client) {
|
||||
|
||||
try {
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE,
|
||||
OAuth2GrantType.REFRESH_TOKEN.getValue())
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
final OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
|
||||
final OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
final String responseData = postMethod.getResponseBodyAsString();
|
||||
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + responseData);
|
||||
|
||||
if (responseData != null && responseData.length() > 0) {
|
||||
final JSONObject tokenJson = new JSONObject(responseData);
|
||||
|
||||
final Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
|
||||
final RemoteOperationResult<Map<String, String>> result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
return (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null)
|
||||
? new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR)
|
||||
: result;
|
||||
} else {
|
||||
return new RemoteOperationResult<>(postMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return new RemoteOperationResult<>(e);
|
||||
}
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
|
||||
public interface OAuth2RequestBuilder {
|
||||
|
||||
enum OAuthRequest {
|
||||
GET_AUTHORIZATION_CODE, CREATE_ACCESS_TOKEN, REFRESH_ACCESS_TOKEN
|
||||
}
|
||||
|
||||
void setRequest(OAuthRequest operation);
|
||||
|
||||
void setGrantType(OAuth2GrantType grantType);
|
||||
|
||||
void setAuthorizationCode(String code);
|
||||
|
||||
void setRefreshToken(String refreshToken);
|
||||
|
||||
RemoteOperation buildOperation();
|
||||
|
||||
String buildUri();
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class OAuth2ResponseParser {
|
||||
|
||||
Map<String, String> parseAccessTokenResult(JSONObject tokenJson) throws JSONException {
|
||||
Map<String, String> resultTokenMap = new HashMap<>();
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ACCESS_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_TOKEN_TYPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_EXPIRES_IN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_REFRESH_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_SCOPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_URI));
|
||||
}
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard
|
||||
resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson.
|
||||
getString(OAuth2Constants.KEY_USER_ID));
|
||||
}
|
||||
|
||||
return resultTokenMap;
|
||||
}
|
||||
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
public class OwnCloudOAuth2Provider implements OAuth2Provider {
|
||||
|
||||
public static final String NAME = OAuth2Provider.class.getName();
|
||||
|
||||
public static final String ACCESS_TOKEN_ENDPOINT_PATH = "index.php/apps/oauth2/api/v1/token";
|
||||
private static final String AUTHORIZATION_CODE_ENDPOINT_PATH = "index.php/apps/oauth2/authorize";
|
||||
|
||||
private String mAuthorizationServerUrl = "";
|
||||
private String mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
private String mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
|
||||
private OAuth2ClientConfiguration mClientConfiguration;
|
||||
|
||||
@Override
|
||||
public OAuth2RequestBuilder getOperationBuilder() {
|
||||
return new OwnCloudOAuth2RequestBuilder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
|
||||
mClientConfiguration = oAuth2ClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2ClientConfiguration getClientConfiguration() {
|
||||
return mClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationServerUri(String authorizationServerUri) {
|
||||
mAuthorizationServerUrl = authorizationServerUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationServerUri() {
|
||||
return mAuthorizationServerUrl;
|
||||
}
|
||||
|
||||
public String getAccessTokenEndpointPath() {
|
||||
return mAccessTokenEndpointPath;
|
||||
}
|
||||
|
||||
public void setAccessTokenEndpointPath(String accessTokenEndpointPath) {
|
||||
if (accessTokenEndpointPath == null || accessTokenEndpointPath.length() <= 0) {
|
||||
Log_OC.w(NAME, "Setting invalid access token endpoint path, going on with default");
|
||||
mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAccessTokenEndpointPath = accessTokenEndpointPath;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthorizationCodeEndpointPath() {
|
||||
return mAuthorizationCodeEndpointPath;
|
||||
}
|
||||
|
||||
public void setAuthorizationCodeEndpointPath(String authorizationCodeEndpointPath) {
|
||||
if (authorizationCodeEndpointPath == null || authorizationCodeEndpointPath.length() <= 0) {
|
||||
Log_OC.w(NAME, "Setting invalid authorization code endpoint path, going on with default");
|
||||
mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAuthorizationCodeEndpointPath = authorizationCodeEndpointPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
|
||||
public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
|
||||
|
||||
private OwnCloudOAuth2Provider mOAuth2Provider;
|
||||
|
||||
private OAuthRequest mRequest;
|
||||
private OAuth2GrantType mGrantType = OAuth2GrantType.AUTHORIZATION_CODE;
|
||||
private String mCode;
|
||||
private String mRefreshToken;
|
||||
|
||||
public OwnCloudOAuth2RequestBuilder(OwnCloudOAuth2Provider ownCloudOAuth2Provider) {
|
||||
mOAuth2Provider = ownCloudOAuth2Provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequest(OAuthRequest request) {
|
||||
mRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGrantType(OAuth2GrantType grantType) {
|
||||
mGrantType = grantType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationCode(String code) {
|
||||
mCode = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
mRefreshToken = refreshToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteOperation buildOperation() {
|
||||
if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE &&
|
||||
mGrantType != OAuth2GrantType.REFRESH_TOKEN) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " +
|
||||
OAuth2GrantType.REFRESH_TOKEN + " are supported"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
|
||||
switch(mRequest) {
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
return new OAuth2GetAccessTokenOperation(
|
||||
mGrantType.getValue(),
|
||||
mCode,
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
clientConfiguration.getRedirectUri(),
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
|
||||
case REFRESH_ACCESS_TOKEN:
|
||||
return new OAuth2RefreshAccessTokenOperation(
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
mRefreshToken,
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildUri() {
|
||||
if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
Uri uri;
|
||||
Uri.Builder uriBuilder;
|
||||
switch(mRequest) {
|
||||
case GET_AUTHORIZATION_CODE:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
|
||||
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
|
||||
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
|
||||
/**
|
||||
* Client used to perform network operations
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class HttpClient {
|
||||
private static final String TAG = HttpClient.class.toString();
|
||||
|
||||
private static OkHttpClient sOkHttpClient;
|
||||
private static HttpInterceptor sOkHttpInterceptor;
|
||||
private static Context sContext;
|
||||
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
|
||||
|
||||
public static void setContext(Context context) {
|
||||
sContext = context;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return sContext;
|
||||
}
|
||||
|
||||
public static OkHttpClient getOkHttpClient() {
|
||||
if (sOkHttpClient == null) {
|
||||
try {
|
||||
final X509TrustManager trustManager = new AdvancedX509TrustManager(
|
||||
NetworkUtils.getKnownServersStore(sContext));
|
||||
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[] {trustManager}, null);
|
||||
|
||||
// Automatic cookie handling, NOT PERSISTENT
|
||||
CookieJar cookieJar = new CookieJar() {
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
// Avoid duplicated cookies
|
||||
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>();
|
||||
nonDuplicatedCookiesSet.addAll(cookies);
|
||||
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>();
|
||||
nonDuplicatedCookiesList.addAll(nonDuplicatedCookiesSet);
|
||||
|
||||
sCookieStore.put(url.host(), nonDuplicatedCookiesList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||
List<Cookie> cookies = sCookieStore.get(url.host());
|
||||
return cookies != null ? cookies : new ArrayList<>();
|
||||
}
|
||||
};
|
||||
|
||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
|
||||
.addInterceptor(getOkHttpInterceptor())
|
||||
.protocols(Arrays.asList(Protocol.HTTP_1_1))
|
||||
.readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.followRedirects(false)
|
||||
.sslSocketFactory(sslContext.getSocketFactory(), trustManager)
|
||||
.hostnameVerifier((asdf, usdf) -> true)
|
||||
.cookieJar(cookieJar);
|
||||
// TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok.
|
||||
//.hostnameVerifier(new BrowserCompatHostnameVerifier());
|
||||
sOkHttpClient = clientBuilder.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Could not setup SSL system.", e);
|
||||
}
|
||||
}
|
||||
return sOkHttpClient;
|
||||
}
|
||||
|
||||
private static HttpInterceptor getOkHttpInterceptor() {
|
||||
if (sOkHttpInterceptor == null) {
|
||||
sOkHttpInterceptor = new HttpInterceptor();
|
||||
addHeaderForAllRequests(HttpConstants.USER_AGENT_HEADER, OwnCloudClientManagerFactory.getUserAgent());
|
||||
addHeaderForAllRequests(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
|
||||
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
|
||||
}
|
||||
return sOkHttpInterceptor;
|
||||
}
|
||||
|
||||
public void disableAutomaticCookiesHandling() {
|
||||
OkHttpClient.Builder clientBuilder = getOkHttpClient().newBuilder();
|
||||
clientBuilder.cookieJar(new CookieJar() {
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
});
|
||||
sOkHttpClient = clientBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
getOkHttpInterceptor()
|
||||
.addRequestInterceptor(
|
||||
new RequestHeaderInterceptor(headerName, headerValue)
|
||||
);
|
||||
}
|
||||
|
||||
public static void deleteHeaderForAllRequests(String headerName) {
|
||||
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
|
||||
}
|
||||
|
||||
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
|
||||
return sCookieStore.get(httpUrl.host());
|
||||
}
|
||||
|
||||
public void clearCookies() {
|
||||
sCookieStore.clear();
|
||||
}
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
/**
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class HttpConstants {
|
||||
|
||||
/***********************************************************************************************************
|
||||
*************************************************** HEADERS ***********************************************
|
||||
***********************************************************************************************************/
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String COOKIE_HEADER = "Cookie";
|
||||
public static final String BEARER_AUTHORIZATION_KEY = "Bearer ";
|
||||
public static final String USER_AGENT_HEADER = "User-Agent";
|
||||
public static final String IF_MATCH_HEADER = "If-Match";
|
||||
public static final String IF_NONE_MATCH_HEADER = "If-None-Match";
|
||||
public static final String CONTENT_TYPE_HEADER = "Content-Type";
|
||||
public static final String CONTENT_LENGTH_HEADER = "Content-Length";
|
||||
public static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
||||
public static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
||||
public static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
|
||||
public static final String OC_X_REQUEST_ID = "X-Request-ID";
|
||||
public static final String LOCATION_HEADER = "Location";
|
||||
public static final String LOCATION_HEADER_LOWER = "location";
|
||||
public static final String CONTENT_TYPE_URLENCODED_UTF8 = "application/x-www-form-urlencoded; charset=utf-8";
|
||||
public static final String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
|
||||
public static final String ACCEPT_ENCODING_IDENTITY = "identity";
|
||||
|
||||
/***********************************************************************************************************
|
||||
************************************************ STATUS CODES *********************************************
|
||||
***********************************************************************************************************/
|
||||
|
||||
/**
|
||||
* 1xx Informational
|
||||
*/
|
||||
|
||||
// 100 Continue (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_CONTINUE = 100;
|
||||
// 101 Switching Protocols (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_SWITCHING_PROTOCOLS = 101;
|
||||
// 102 Processing (WebDAV - RFC 2518)
|
||||
public static final int HTTP_PROCESSING = 102;
|
||||
|
||||
/**
|
||||
* 2xx Success
|
||||
*/
|
||||
|
||||
// 200 OK (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_OK = 200;
|
||||
// 201 Created (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_CREATED = 201;
|
||||
// 202 Accepted (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_ACCEPTED = 202;
|
||||
// 203 Non Authoritative Information (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
|
||||
// 204 No Content</tt> (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_NO_CONTENT = 204;
|
||||
// 205 Reset Content</tt> (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_RESET_CONTENT = 205;
|
||||
// 206 Partial Content</tt> (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_PARTIAL_CONTENT = 206;
|
||||
//207 Multi-Status (WebDAV - RFC 2518) or 207 Partial Update OK (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?)
|
||||
public static final int HTTP_MULTI_STATUS = 207;
|
||||
|
||||
/**
|
||||
* 3xx Redirection
|
||||
*/
|
||||
|
||||
// 300 Mutliple Choices</tt> (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_MULTIPLE_CHOICES = 300;
|
||||
// 301 Moved Permanently</tt> (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_MOVED_PERMANENTLY = 301;
|
||||
// 302 Moved Temporarily</tt> (Sometimes <tt>Found) (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_MOVED_TEMPORARILY = 302;
|
||||
// 303 See Other (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_SEE_OTHER = 303;
|
||||
// 304 Not Modified (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_NOT_MODIFIED = 304;
|
||||
// 305 Use Proxy (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_USE_PROXY = 305;
|
||||
// 307 Temporary Redirect (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_TEMPORARY_REDIRECT = 307;
|
||||
|
||||
/**
|
||||
* 4xx Client Error
|
||||
*/
|
||||
|
||||
// 400 Bad Request (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_BAD_REQUEST = 400;
|
||||
// 401 Unauthorized (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_UNAUTHORIZED = 401;
|
||||
// 402 Payment Required (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_PAYMENT_REQUIRED = 402;
|
||||
// 403 Forbidden (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_FORBIDDEN = 403;
|
||||
// 404 Not Found (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_NOT_FOUND = 404;
|
||||
// 405 Method Not Allowed (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_METHOD_NOT_ALLOWED = 405;
|
||||
// 406 Not Acceptable (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_NOT_ACCEPTABLE = 406;
|
||||
// 407 Proxy Authentication Required (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||
// 408 Request Timeout (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_REQUEST_TIMEOUT = 408;
|
||||
// 409 Conflict (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_CONFLICT = 409;
|
||||
// 410 Gone (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_GONE = 410;
|
||||
// 411 Length Required (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_LENGTH_REQUIRED = 411;
|
||||
// 412 Precondition Failed (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_PRECONDITION_FAILED = 412;
|
||||
// 413 Request Entity Too Large (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_REQUEST_TOO_LONG = 413;
|
||||
// 414 Request-URI Too Long (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_REQUEST_URI_TOO_LONG = 414;
|
||||
// 415 Unsupported Media Type (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
|
||||
// 416 Requested Range Not Satisfiable (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||
// 417 Expectation Failed (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_EXPECTATION_FAILED = 417;
|
||||
// 419 Insufficient Space on Resource (WebDAV - draft-ietf-webdav-protocol-05?)
|
||||
// or <tt>419 Proxy Reauthentication Required (HTTP/1.1 drafts?)
|
||||
public static final int HTTP_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
|
||||
// 420 Method Failure (WebDAV - draft-ietf-webdav-protocol-05?)
|
||||
public static final int HTTP_METHOD_FAILURE = 420;
|
||||
// 422 Unprocessable Entity (WebDAV - RFC 2518)
|
||||
public static final int HTTP_UNPROCESSABLE_ENTITY = 422;
|
||||
// 423 Locked (WebDAV - RFC 2518)
|
||||
public static final int HTTP_LOCKED = 423;
|
||||
// 424 Failed Dependency (WebDAV - RFC 2518)
|
||||
public static final int HTTP_FAILED_DEPENDENCY = 424;
|
||||
|
||||
/**
|
||||
* 5xx Client Error
|
||||
*/
|
||||
|
||||
// 500 Server Error (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||
// 501 Not Implemented (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_NOT_IMPLEMENTED = 501;
|
||||
// 502 Bad Gateway (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_BAD_GATEWAY = 502;
|
||||
// 503 Service Unavailable (HTTP/1.0 - RFC 1945)
|
||||
public static final int HTTP_SERVICE_UNAVAILABLE = 503;
|
||||
// 504 Gateway Timeout (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_GATEWAY_TIMEOUT = 504;
|
||||
// 505 HTTP Version Not Supported (HTTP/1.1 - RFC 2616)
|
||||
public static final int HTTP_HTTP_VERSION_NOT_SUPPORTED = 505;
|
||||
// 507 Insufficient Storage (WebDAV - RFC 2518)
|
||||
public static final int HTTP_INSUFFICIENT_STORAGE = 507;
|
||||
|
||||
/***********************************************************************************************************
|
||||
*************************************************** TIMEOUTS **********************************************
|
||||
***********************************************************************************************************/
|
||||
|
||||
/** Default timeout for waiting data from the server */
|
||||
public static final int DEFAULT_DATA_TIMEOUT = 60000;
|
||||
|
||||
/** Default timeout for establishing a connection */
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
for (RequestInterceptor interceptor : mRequestInterceptors) {
|
||||
request = interceptor.intercept(request);
|
||||
}
|
||||
|
||||
Response response = chain.proceed(request);
|
||||
|
||||
for (ResponseInterceptor interceptor : mResponseInterceptors) {
|
||||
response = interceptor.intercept(response);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public interface RequestInterceptor {
|
||||
Request intercept(Request request) throws IOException;
|
||||
}
|
||||
|
||||
public interface ResponseInterceptor {
|
||||
Response intercept(Response response) throws IOException;
|
||||
}
|
||||
|
||||
public HttpInterceptor addRequestInterceptor(RequestInterceptor requestInterceptor) {
|
||||
mRequestInterceptors.add(requestInterceptor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpInterceptor addResponseInterceptor (ResponseInterceptor responseInterceptor) {
|
||||
mResponseInterceptors.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) {
|
||||
Iterator<RequestInterceptor> requestInterceptorIterator = mRequestInterceptors.iterator();
|
||||
while (requestInterceptorIterator.hasNext()) {
|
||||
RequestInterceptor currentRequestInterceptor = requestInterceptorIterator.next();
|
||||
if (currentRequestInterceptor instanceof RequestHeaderInterceptor &&
|
||||
((RequestHeaderInterceptor) currentRequestInterceptor).getHeaderName().equals(headerName)) {
|
||||
requestInterceptorIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<ResponseInterceptor> getResponseInterceptors() {
|
||||
return mResponseInterceptors;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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;
|
||||
}
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 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 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();
|
||||
}
|
||||
|
||||
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
|
||||
mOkHttpClient = mOkHttpClient.newBuilder()
|
||||
.retryOnConnectionFailure(retryOnConnectionFailure)
|
||||
.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();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* OkHttp delete calls wrapper
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class DeleteMethod extends HttpMethod{
|
||||
|
||||
public DeleteMethod(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws IOException {
|
||||
mRequest = mRequest.newBuilder()
|
||||
.delete()
|
||||
.build();
|
||||
|
||||
return super.onExecute();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* OkHttp get calls wrapper
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class GetMethod extends HttpMethod {
|
||||
|
||||
public GetMethod(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws IOException {
|
||||
mRequest = mRequest.newBuilder()
|
||||
.get()
|
||||
.build();
|
||||
|
||||
return super.onExecute();
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* Wrapper to perform OkHttp calls
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public abstract class HttpMethod extends HttpBaseMethod {
|
||||
|
||||
public HttpMethod(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws IOException {
|
||||
mCall = mOkHttpClient.newCall(mRequest);
|
||||
mResponse = mCall.execute();
|
||||
return super.getStatusCode();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* OkHttp post calls wrapper
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class PostMethod extends HttpMethod {
|
||||
|
||||
public PostMethod(URL url){
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws IOException {
|
||||
mRequest = mRequest.newBuilder()
|
||||
.post(mRequestBody)
|
||||
.build();
|
||||
|
||||
return super.onExecute();
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
public class PutMethod extends HttpMethod{
|
||||
|
||||
public PutMethod(URL url){
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws IOException {
|
||||
mRequest = mRequest.newBuilder()
|
||||
.put(mRequestBody)
|
||||
.build();
|
||||
|
||||
return super.onExecute();
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.net.URL;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
/**
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class DavConstants {
|
||||
public static final int DEPTH_0 = 0;
|
||||
public static final int DEPTH_1 = 1;
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import at.bitfire.dav4android.Constants;
|
||||
import at.bitfire.dav4android.DavOCResource;
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import at.bitfire.dav4android.exception.RedirectException;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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 setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
|
||||
super.setRetryOnConnectionFailure(retryOnConnectionFailure);
|
||||
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());
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Getter
|
||||
//////////////////////////////
|
||||
|
||||
@Override
|
||||
public boolean getRetryOnConnectionFailure() {
|
||||
return false; //TODO: implement me
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAborted() {
|
||||
return mDavResource.isCallAborted();
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.net.URL;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* MkCol calls wrapper
|
||||
* @author Christian Schabesberger
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class MkColMethod extends DavMethod {
|
||||
public MkColMethod(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onExecute() throws Exception {
|
||||
mDavResource.mkCol(null, response -> {
|
||||
mResponse = response;
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
return super.getStatusCode();
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.net.URL;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import at.bitfire.dav4android.Property;
|
||||
import at.bitfire.dav4android.Response;
|
||||
import at.bitfire.dav4android.exception.DavException;
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertStoreException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class AdvancedX509TrustManager implements X509TrustManager {
|
||||
|
||||
private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
|
||||
|
||||
private X509TrustManager mStandardTrustManager = null;
|
||||
private KeyStore mKnownServersKeyStore;
|
||||
|
||||
/**
|
||||
* Constructor for AdvancedX509TrustManager
|
||||
*
|
||||
* @param knownServersKeyStore Local certificates store with server certificates explicitly trusted by the user.
|
||||
* @throws CertStoreException When no default X509TrustManager instance was found in the system.
|
||||
*/
|
||||
public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
|
||||
throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
|
||||
super();
|
||||
TrustManagerFactory factory = TrustManagerFactory
|
||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
factory.init((KeyStore)null);
|
||||
mStandardTrustManager = findX509TrustManager(factory);
|
||||
|
||||
mKnownServersKeyStore = knownServersKeyStore;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locates the first X509TrustManager provided by a given TrustManagerFactory
|
||||
* @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
|
||||
* @return The first X509TrustManager found in factory.
|
||||
* @throws CertStoreException When no X509TrustManager instance was found in factory
|
||||
*/
|
||||
private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
|
||||
TrustManager tms[] = factory.getTrustManagers();
|
||||
for (int i = 0; i < tms.length; i++) {
|
||||
if (tms[i] instanceof X509TrustManager) {
|
||||
return (X509TrustManager) tms[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
|
||||
* String authType)
|
||||
*/
|
||||
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
|
||||
mStandardTrustManager.checkClientTrusted(certificates, authType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
|
||||
* String authType)
|
||||
*/
|
||||
public void checkServerTrusted(X509Certificate[] certificates, String authType) {
|
||||
if (!isKnownServer(certificates[0])) {
|
||||
CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
|
||||
try {
|
||||
certificates[0].checkValidity();
|
||||
} catch (CertificateExpiredException c) {
|
||||
result.setCertificateExpiredException(c);
|
||||
|
||||
} catch (CertificateNotYetValidException c) {
|
||||
result.setCertificateNotYetException(c);
|
||||
}
|
||||
|
||||
try {
|
||||
mStandardTrustManager.checkServerTrusted(certificates, authType);
|
||||
} catch (CertificateException c) {
|
||||
Throwable cause = c.getCause();
|
||||
Throwable previousCause = null;
|
||||
while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) { // getCause() is not funny
|
||||
previousCause = cause;
|
||||
cause = cause.getCause();
|
||||
}
|
||||
if (cause != null && cause instanceof CertPathValidatorException) {
|
||||
result.setCertPathValidatorException((CertPathValidatorException)cause);
|
||||
} else {
|
||||
result.setOtherCertificateException(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isException())
|
||||
throw result;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
|
||||
*/
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return mStandardTrustManager.getAcceptedIssuers();
|
||||
}
|
||||
|
||||
|
||||
public boolean isKnownServer(X509Certificate cert) {
|
||||
try {
|
||||
return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
|
||||
} catch (KeyStoreException e) {
|
||||
Log_OC.d(TAG, "Fail while checking certificate in the known-servers store");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
||||
/**
|
||||
* Exception joining all the problems that {@link AdvancedX509TrustManager} can find in
|
||||
* a certificate chain for a server.
|
||||
*
|
||||
* This was initially created as an extension of CertificateException, but some
|
||||
* implementations of the SSL socket layer in existing devices are REPLACING the CertificateException
|
||||
* instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)}
|
||||
* with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it.
|
||||
*
|
||||
* Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException
|
||||
* instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}.
|
||||
*
|
||||
* BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it
|
||||
* in client methods. Be sure to use it only when you know exactly where it will go.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class CertificateCombinedException extends RuntimeException {
|
||||
|
||||
/** Generated - to refresh every time the class changes */
|
||||
private static final long serialVersionUID = -8875782030758554999L;
|
||||
|
||||
private X509Certificate mServerCert = null;
|
||||
private String mHostInUrl;
|
||||
|
||||
private CertificateExpiredException mCertificateExpiredException = null;
|
||||
private CertificateNotYetValidException mCertificateNotYetValidException = null;
|
||||
private CertPathValidatorException mCertPathValidatorException = null;
|
||||
private CertificateException mOtherCertificateException = null;
|
||||
private SSLPeerUnverifiedException mSslPeerUnverifiedException = null;
|
||||
|
||||
public CertificateCombinedException(X509Certificate x509Certificate) {
|
||||
mServerCert = x509Certificate;
|
||||
}
|
||||
|
||||
public X509Certificate getServerCertificate() {
|
||||
return mServerCert;
|
||||
}
|
||||
|
||||
public String getHostInUrl() {
|
||||
return mHostInUrl;
|
||||
}
|
||||
|
||||
public void setHostInUrl(String host) {
|
||||
mHostInUrl = host;
|
||||
}
|
||||
|
||||
public CertificateExpiredException getCertificateExpiredException() {
|
||||
return mCertificateExpiredException;
|
||||
}
|
||||
|
||||
public void setCertificateExpiredException(CertificateExpiredException c) {
|
||||
mCertificateExpiredException = c;
|
||||
}
|
||||
|
||||
public CertificateNotYetValidException getCertificateNotYetValidException() {
|
||||
return mCertificateNotYetValidException;
|
||||
}
|
||||
|
||||
public void setCertificateNotYetException(CertificateNotYetValidException c) {
|
||||
mCertificateNotYetValidException = c;
|
||||
}
|
||||
|
||||
public CertPathValidatorException getCertPathValidatorException() {
|
||||
return mCertPathValidatorException;
|
||||
}
|
||||
|
||||
public void setCertPathValidatorException(CertPathValidatorException c) {
|
||||
mCertPathValidatorException = c;
|
||||
}
|
||||
|
||||
public CertificateException getOtherCertificateException() {
|
||||
return mOtherCertificateException;
|
||||
}
|
||||
|
||||
public void setOtherCertificateException(CertificateException c) {
|
||||
mOtherCertificateException = c;
|
||||
}
|
||||
|
||||
public SSLPeerUnverifiedException getSslPeerUnverifiedException() {
|
||||
return mSslPeerUnverifiedException ;
|
||||
}
|
||||
|
||||
public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) {
|
||||
mSslPeerUnverifiedException = s;
|
||||
}
|
||||
|
||||
public boolean isException() {
|
||||
return (mCertificateExpiredException != null ||
|
||||
mCertificateNotYetValidException != null ||
|
||||
mCertPathValidatorException != null ||
|
||||
mOtherCertificateException != null ||
|
||||
mSslPeerUnverifiedException != null);
|
||||
}
|
||||
|
||||
public boolean isRecoverable() {
|
||||
return (mCertificateExpiredException != null ||
|
||||
mCertificateNotYetValidException != null ||
|
||||
mCertPathValidatorException != null ||
|
||||
mSslPeerUnverifiedException != null);
|
||||
}
|
||||
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Iterator;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okio.BufferedSink;
|
||||
|
||||
/**
|
||||
* A Request body that represents a file chunk and include information about the progress when uploading it
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||
|
||||
private static final String TAG = ChunkFromFileRequestBody.class.getSimpleName();
|
||||
|
||||
//private final File mFile;
|
||||
private final FileChannel mChannel;
|
||||
private final long mChunkSize;
|
||||
private long mOffset;
|
||||
private long mTransferred;
|
||||
private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
|
||||
|
||||
public ChunkFromFileRequestBody(File file, MediaType contentType, FileChannel channel, long chunkSize) {
|
||||
super(file, contentType);
|
||||
if (channel == null) {
|
||||
throw new IllegalArgumentException("File may not be null");
|
||||
}
|
||||
if (chunkSize <= 0) {
|
||||
throw new IllegalArgumentException("Chunk size must be greater than zero");
|
||||
}
|
||||
this.mChannel = channel;
|
||||
this.mChunkSize = chunkSize;
|
||||
mOffset = 0;
|
||||
mTransferred = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() {
|
||||
try {
|
||||
return Math.min(mChunkSize, mChannel.size() - mChannel.position());
|
||||
} catch (IOException e) {
|
||||
return mChunkSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) {
|
||||
int readCount;
|
||||
Iterator<OnDatatransferProgressListener> it;
|
||||
|
||||
try {
|
||||
mChannel.position(mOffset);
|
||||
long size = mFile.length();
|
||||
if (size == 0) size = -1;
|
||||
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
||||
while (mChannel.position() < maxCount) {
|
||||
|
||||
|
||||
Log_OC.d(TAG, "Sink buffer size: " + sink.buffer().size());
|
||||
|
||||
readCount = mChannel.read(mBuffer);
|
||||
|
||||
Log_OC.d(TAG, "Read " + readCount + " bytes from file channel to " + mBuffer.toString());
|
||||
|
||||
sink.buffer().write(mBuffer.array(), 0 ,readCount);
|
||||
|
||||
sink.flush();
|
||||
|
||||
Log_OC.d(TAG, "Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size());
|
||||
|
||||
mBuffer.clear();
|
||||
if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
|
||||
mTransferred += readCount;
|
||||
}
|
||||
synchronized (mDataTransferListeners) {
|
||||
it = mDataTransferListeners.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next().onTransferProgress(readCount, mTransferred, size, mFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "Chunk with size " + mChunkSize + " written in request body");
|
||||
|
||||
} catch (Exception exception) {
|
||||
|
||||
Log.e(TAG, exception.toString());
|
||||
// // any read problem will be handled as if the file is not there
|
||||
// if (io instanceof FileNotFoundException) {
|
||||
// throw io;
|
||||
// } else {
|
||||
// FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
|
||||
// fnf.initCause(io);
|
||||
// throw fnf;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public void setOffset(long offset) {
|
||||
this.mOffset = offset;
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okio.BufferedSink;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
|
||||
/**
|
||||
* A Request body that represents a file and include information about the progress when uploading it
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
|
||||
|
||||
private static final String TAG = FileRequestBody.class.getSimpleName();
|
||||
|
||||
protected File mFile;
|
||||
private MediaType mContentType;
|
||||
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||
|
||||
public FileRequestBody(File file, MediaType contentType) {
|
||||
mFile = file;
|
||||
mContentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType contentType() {
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() {
|
||||
return mFile.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) {
|
||||
Source source;
|
||||
Iterator<OnDatatransferProgressListener> it;
|
||||
try {
|
||||
source = Okio.source(mFile);
|
||||
|
||||
long transferred = 0;
|
||||
long read;
|
||||
|
||||
while ((read = source.read(sink.buffer(), 4096)) != -1) {
|
||||
transferred += read;
|
||||
sink.flush();
|
||||
synchronized (mDataTransferListeners) {
|
||||
it = mDataTransferListeners.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next().onTransferProgress(read, transferred, mFile.length(), mFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "File with name " + mFile.getName() + " and size " + mFile.length() +
|
||||
" written in request body");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.addAll(listeners);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
|
||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
final private static String TAG = NetworkUtils.class.getSimpleName();
|
||||
|
||||
/** Default timeout for waiting data from the server */
|
||||
public static final int DEFAULT_DATA_TIMEOUT = 60000;
|
||||
|
||||
/** Default timeout for establishing a connection */
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
|
||||
/** Standard name for protocol TLS version 1.2 in Java Secure Socket Extension (JSSE) API */
|
||||
public static final String PROTOCOL_TLSv1_2 = "TLSv1.2";
|
||||
|
||||
/** Standard name for protocol TLS version 1.0 in JSSE API */
|
||||
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
|
||||
|
||||
private static X509HostnameVerifier mHostnameVerifier = null;
|
||||
|
||||
private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
|
||||
|
||||
private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
|
||||
|
||||
private static KeyStore mKnownServersStore = null;
|
||||
|
||||
/**
|
||||
* Returns the local store of reliable server certificates, explicitly accepted by the user.
|
||||
*
|
||||
* Returns a KeyStore instance with empty content if the local store was never created.
|
||||
*
|
||||
* Loads the store from the storage environment if needed.
|
||||
*
|
||||
* @param context Android context where the operation is being performed.
|
||||
* @return KeyStore instance with explicitly-accepted server certificates.
|
||||
* @throws KeyStoreException When the KeyStore instance could not be created.
|
||||
* @throws IOException When an existing local trust store could not be loaded.
|
||||
* @throws NoSuchAlgorithmException When the existing local trust store was saved with an unsupported algorithm.
|
||||
* @throws CertificateException When an exception occurred while loading the certificates from the local
|
||||
* trust store.
|
||||
*/
|
||||
public static KeyStore getKnownServersStore(Context context)
|
||||
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
|
||||
if (mKnownServersStore == null) {
|
||||
//mKnownServersStore = KeyStore.getInstance("BKS");
|
||||
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
|
||||
Log_OC.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
|
||||
if (localTrustStoreFile.exists()) {
|
||||
InputStream in = new FileInputStream(localTrustStoreFile);
|
||||
try {
|
||||
mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
} else {
|
||||
// next is necessary to initialize an empty KeyStore instance
|
||||
mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
|
||||
}
|
||||
}
|
||||
return mKnownServersStore;
|
||||
}
|
||||
|
||||
|
||||
public static void addCertToKnownServersStore(Certificate cert, Context context)
|
||||
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||
|
||||
KeyStore knownServers = getKnownServersStore(context);
|
||||
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
|
||||
knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCertInKnownServersStore(Certificate cert, Context context)
|
||||
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||
|
||||
KeyStore knownServers = getKnownServersStore(context);
|
||||
Log_OC.d(TAG, "Certificate - HashCode: " + cert.hashCode() + " "
|
||||
+ Boolean.toString(knownServers.isCertificateEntry(Integer.toString(cert.hashCode()))));
|
||||
return knownServers.isCertificateEntry(Integer.toString(cert.hashCode()));
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
public interface OnDatatransferProgressListener {
|
||||
void onTransferProgress(long read, long transferred, long percent, String absolutePath);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface ProgressiveDataTransferer {
|
||||
|
||||
public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
|
||||
|
||||
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
|
||||
|
||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
|
||||
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
|
||||
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
|
||||
* {@link RemoteOperation}, and the status codes corresponding to all
|
||||
* of them.
|
||||
*
|
||||
* The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
|
||||
* the maximum length of redirections allowed by the {@link com.owncloud.android.lib.common.OwnCloudClient} instance
|
||||
* that ran the operation.
|
||||
*
|
||||
* If no redirection was followed, the last (and first) status code contained corresponds to the original URL in the
|
||||
* request.
|
||||
*/
|
||||
public class RedirectionPath {
|
||||
|
||||
private int[] mStatuses = null;
|
||||
|
||||
private int mLastStatus = -1;
|
||||
|
||||
private String[] mLocations = null;
|
||||
|
||||
private int mLastLocation = -1;
|
||||
|
||||
/**
|
||||
* Public constructor.
|
||||
*
|
||||
* @param status Status code resulting of executing a request on the original URL.
|
||||
* @param maxRedirections Maximum number of redirections that will be contained.
|
||||
* @throws IllegalArgumentException If 'maxRedirections' is < 0
|
||||
*/
|
||||
public RedirectionPath(int status, int maxRedirections) {
|
||||
if (maxRedirections < 0) {
|
||||
throw new IllegalArgumentException("maxRedirections MUST BE zero or greater");
|
||||
}
|
||||
mStatuses = new int[maxRedirections + 1];
|
||||
Arrays.fill(mStatuses, -1);
|
||||
mStatuses[++mLastStatus] = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new location URL to the list of followed redirections.
|
||||
*
|
||||
* @param location URL extracted from a 'Location' header in a redirection.
|
||||
*/
|
||||
public void addLocation(String location) {
|
||||
if (mLocations == null) {
|
||||
mLocations = new String[mStatuses.length - 1];
|
||||
}
|
||||
if (mLastLocation < mLocations.length - 1) {
|
||||
mLocations[++mLastLocation] = location;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new status code to the list of status corresponding to followed redirections.
|
||||
*
|
||||
* @param status Status code from the response of another followed redirection.
|
||||
*/
|
||||
public void addStatus(int status) {
|
||||
if (mLastStatus < mStatuses.length - 1) {
|
||||
mStatuses[++mLastStatus] = status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last status code saved.
|
||||
*/
|
||||
public int getLastStatus() {
|
||||
return mStatuses[mLastStatus];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last location followed corresponding to a permanent redirection (status code 301).
|
||||
*/
|
||||
public String getLastPermanentLocation() {
|
||||
for (int i = mLastStatus; i >= 0; i--) {
|
||||
if (mStatuses[i] == HttpConstants.HTTP_MOVED_PERMANENTLY && i <= mLastLocation) {
|
||||
return mLocations[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Count of locations.
|
||||
*/
|
||||
public int getRedirectionsCount() {
|
||||
return mLastLocation + 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
|
||||
/**
|
||||
* Enables the support of Server Name Indication if existing
|
||||
* in the underlying network implementation.
|
||||
*
|
||||
* Build as a singleton.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class ServerNameIndicator {
|
||||
|
||||
private static final String TAG = ServerNameIndicator.class.getSimpleName();
|
||||
|
||||
private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
|
||||
|
||||
private static final String METHOD_NAME = "setHostname";
|
||||
|
||||
private final WeakReference<Class<?>> mSSLSocketClassRef;
|
||||
private final WeakReference<Method> mSetHostnameMethodRef;
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor, class is a singleton.
|
||||
*
|
||||
* @param sslSocketClass Underlying implementation class of {@link SSLSocket} used to connect with the server.
|
||||
* @param setHostnameMethod Name of the method to call to enable the SNI support.
|
||||
*/
|
||||
private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
|
||||
mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
|
||||
mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the {@code #setHostname(String)} method of the underlying implementation
|
||||
* of {@link SSLSocket} if exists.
|
||||
*
|
||||
* Creates and initializes the single instance of the class when needed
|
||||
*
|
||||
* @param hostname The name of the server host of interest.
|
||||
* @param sslSocket Client socket to connect with the server.
|
||||
*/
|
||||
public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
|
||||
final Method setHostnameMethod = getMethod(sslSocket);
|
||||
if (setHostnameMethod != null) {
|
||||
try {
|
||||
setHostnameMethod.invoke(sslSocket, hostname);
|
||||
Log_OC.i(TAG, "SNI done, hostname: " + hostname);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
|
||||
}
|
||||
} else {
|
||||
Log_OC.i(TAG, "SNI not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the method to invoke trying to minimize the effective
|
||||
* application of reflection.
|
||||
*
|
||||
* @param sslSocket Instance of the SSL socket to use in connection with server.
|
||||
* @return Method to call to indicate the server name of interest to the server.
|
||||
*/
|
||||
private static Method getMethod(SSLSocket sslSocket) {
|
||||
final Class<?> sslSocketClass = sslSocket.getClass();
|
||||
final ServerNameIndicator instance = mSingleInstance.get();
|
||||
if (instance == null) {
|
||||
return initFrom(sslSocketClass);
|
||||
|
||||
} else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
|
||||
// the underlying class changed
|
||||
return initFrom(sslSocketClass);
|
||||
|
||||
} else if (instance.mSetHostnameMethodRef == null) {
|
||||
// SNI not supported
|
||||
return null;
|
||||
|
||||
} else {
|
||||
final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
|
||||
return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Singleton initializer.
|
||||
*
|
||||
* Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side.
|
||||
*
|
||||
* @param sslSocketClass Underlying class providing the implementation of {@link SSLSocket}.
|
||||
* @return Method to call to indicate the server name of interest to the server.
|
||||
*/
|
||||
private static Method initFrom(Class<?> sslSocketClass) {
|
||||
Log_OC.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName());
|
||||
Method setHostnameMethod = null;
|
||||
try {
|
||||
setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class);
|
||||
} catch (SecurityException e) {
|
||||
Log_OC.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log_OC.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported");
|
||||
}
|
||||
mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod));
|
||||
return setHostnameMethod;
|
||||
}
|
||||
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
|
||||
public class WebdavUtils {
|
||||
public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
|
||||
"dd.MM.yyyy hh:mm");
|
||||
|
||||
private static final SimpleDateFormat DATETIME_FORMATS[] = {
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
|
||||
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US),
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
|
||||
new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US),
|
||||
new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
|
||||
new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US),
|
||||
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.US)
|
||||
};
|
||||
|
||||
public static Date parseResponseDate(String date) {
|
||||
Date returnDate = null;
|
||||
SimpleDateFormat format = null;
|
||||
for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
|
||||
try {
|
||||
format = DATETIME_FORMATS[i];
|
||||
synchronized(format) {
|
||||
returnDate = format.parse(date);
|
||||
}
|
||||
return returnDate;
|
||||
} catch (ParseException e) {
|
||||
// this is not the format
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a path according to URI RFC 2396.
|
||||
*
|
||||
* If the received path doesn't start with "/", the method adds it.
|
||||
*
|
||||
* @param remoteFilePath Path
|
||||
* @return Encoded path according to RFC 2396, always starting with "/"
|
||||
*/
|
||||
public static String encodePath(String remoteFilePath) {
|
||||
String encodedPath = Uri.encode(remoteFilePath, "/");
|
||||
if (!encodedPath.startsWith("/"))
|
||||
encodedPath = "/" + encodedPath;
|
||||
return encodedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param rawEtag
|
||||
* @return
|
||||
*/
|
||||
public static String parseEtag(String rawEtag) {
|
||||
if (rawEtag == null || rawEtag.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
if (rawEtag.endsWith("-gzip")) {
|
||||
rawEtag = rawEtag.substring(0, rawEtag.length() - 5);
|
||||
}
|
||||
if (rawEtag.length() >= 2 && rawEtag.startsWith("\"") && rawEtag.endsWith("\"")) {
|
||||
rawEtag = rawEtag.substring(1, rawEtag.length() - 1);
|
||||
}
|
||||
return rawEtag;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param httpBaseMethod from which to get the etag
|
||||
* @return etag from response
|
||||
*/
|
||||
public static String getEtagFromResponse(HttpBaseMethod httpBaseMethod) {
|
||||
String eTag = httpBaseMethod.getResponseHeader("OC-ETag");
|
||||
if (eTag == null) {
|
||||
eTag = httpBaseMethod.getResponseHeader("oc-etag");
|
||||
}
|
||||
if (eTag == null) {
|
||||
eTag = httpBaseMethod.getResponseHeader("ETag");
|
||||
}
|
||||
if (eTag == null) {
|
||||
eTag = httpBaseMethod.getResponseHeader("etag");
|
||||
}
|
||||
String result = "";
|
||||
if (eTag != null) {
|
||||
result = eTag;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.network;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
||||
/**
|
||||
* Enforces, if possible, a write timeout for a socket.
|
||||
*
|
||||
* Built as a singleton.
|
||||
*
|
||||
* Tries to hit something like this:
|
||||
* https://android.googlesource.com/platform/external/conscrypt/+/lollipop-release/src/main/java/org/conscrypt/OpenSSLSocketImpl.java#1005
|
||||
*
|
||||
* Minimizes the chances of getting stalled in PUT/POST request if the network interface is lost while
|
||||
* writing the entity into the outwards sockect.
|
||||
*
|
||||
* It happens. See https://github.com/owncloud/android/issues/1684#issuecomment-295306015
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class WriteTimeoutEnforcer {
|
||||
|
||||
private static final String TAG = WriteTimeoutEnforcer.class.getSimpleName();
|
||||
|
||||
private static final AtomicReference<WriteTimeoutEnforcer> mSingleInstance = new AtomicReference<>();
|
||||
|
||||
private static final String METHOD_NAME = "setSoWriteTimeout";
|
||||
|
||||
|
||||
private final WeakReference<Class<?>> mSocketClassRef;
|
||||
private final WeakReference<Method> mSetSoWriteTimeoutMethodRef;
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor, class is a singleton.
|
||||
*
|
||||
* @param socketClass Underlying implementation class of {@link Socket} used to connect
|
||||
* with the server.
|
||||
* @param setSoWriteTimeoutMethod Name of the method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private WriteTimeoutEnforcer(Class<?> socketClass, Method setSoWriteTimeoutMethod) {
|
||||
mSocketClassRef = new WeakReference<Class<?>>(socketClass);
|
||||
mSetSoWriteTimeoutMethodRef =
|
||||
(setSoWriteTimeoutMethod == null) ?
|
||||
null :
|
||||
new WeakReference<>(setSoWriteTimeoutMethod)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the {@code #setSoWrite(int)} method of the underlying implementation
|
||||
* of {@link Socket} if exists.
|
||||
|
||||
* Creates and initializes the single instance of the class when needed
|
||||
*
|
||||
* @param writeTimeoutMilliseconds Write timeout to set, in milliseconds.
|
||||
* @param socket Client socket to connect with the server.
|
||||
*/
|
||||
public static void setSoWriteTimeout(int writeTimeoutMilliseconds, Socket socket) {
|
||||
final Method setSoWriteTimeoutMethod = getMethod(socket);
|
||||
if (setSoWriteTimeoutMethod != null) {
|
||||
try {
|
||||
setSoWriteTimeoutMethod.invoke(socket, writeTimeoutMilliseconds);
|
||||
Log_OC.i(
|
||||
TAG,
|
||||
"Write timeout set in socket, writeTimeoutMilliseconds: "
|
||||
+ writeTimeoutMilliseconds
|
||||
);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e);
|
||||
}
|
||||
} else {
|
||||
Log_OC.i(TAG, "Write timeout for socket not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the method to invoke trying to minimize the cost of reflection reusing objects cached
|
||||
* in static members.
|
||||
*
|
||||
* @param socket Instance of the socket to use in connection with server.
|
||||
* @return Method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private static Method getMethod(Socket socket) {
|
||||
final Class<?> socketClass = socket.getClass();
|
||||
final WriteTimeoutEnforcer instance = mSingleInstance.get();
|
||||
if (instance == null) {
|
||||
return initFrom(socketClass);
|
||||
|
||||
} else if (instance.mSocketClassRef.get() != socketClass) {
|
||||
// the underlying class changed
|
||||
return initFrom(socketClass);
|
||||
|
||||
} else if (instance.mSetSoWriteTimeoutMethodRef == null) {
|
||||
// method not supported
|
||||
return null;
|
||||
|
||||
} else {
|
||||
final Method cachedSetSoWriteTimeoutMethod = instance.mSetSoWriteTimeoutMethodRef.get();
|
||||
return (cachedSetSoWriteTimeoutMethod == null) ?
|
||||
initFrom(socketClass) :
|
||||
cachedSetSoWriteTimeoutMethod
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Singleton initializer.
|
||||
*
|
||||
* Uses reflection to extract and 'cache' the method to invoke to set a write timouet in a socket.
|
||||
*
|
||||
* @param socketClass Underlying class providing the implementation of {@link Socket}.
|
||||
* @return Method to call to set a write timeout in the socket.
|
||||
*/
|
||||
private static Method initFrom(Class<?> socketClass) {
|
||||
Log_OC.i(TAG, "Socket implementation: " + socketClass.getCanonicalName());
|
||||
Method setSoWriteTimeoutMethod = null;
|
||||
try {
|
||||
setSoWriteTimeoutMethod = socketClass.getMethod(METHOD_NAME, int.class);
|
||||
} catch (SecurityException e) {
|
||||
Log_OC.e(TAG, "Could not access to (SocketImpl)#setSoWriteTimeout(int) method ", e);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log_OC.i(
|
||||
TAG,
|
||||
"Could not find (SocketImpl)#setSoWriteTimeout(int) method - write timeout not supported"
|
||||
);
|
||||
}
|
||||
mSingleInstance.set(new WriteTimeoutEnforcer(socketClass, setSoWriteTimeoutMethod));
|
||||
return setSoWriteTimeoutMethod;
|
||||
}
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.operations;
|
||||
|
||||
import android.util.Xml;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Parser for server exceptions
|
||||
* @author davidgonzalez
|
||||
*/
|
||||
public class ErrorMessageParser {
|
||||
// No namespaces
|
||||
private static final String ns = null;
|
||||
|
||||
// Nodes for XML Parser
|
||||
private static final String NODE_ERROR = "d:error";
|
||||
private static final String NODE_MESSAGE = "s:message";
|
||||
|
||||
/**
|
||||
* Parse exception response
|
||||
* @param is
|
||||
* @return errorMessage for an exception
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public String parseXMLResponse(InputStream is) throws XmlPullParserException,
|
||||
IOException {
|
||||
String errorMessage = "";
|
||||
|
||||
try {
|
||||
// XMLPullParser
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||
parser.setInput(is, null);
|
||||
parser.nextTag();
|
||||
errorMessage = readError(parser);
|
||||
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse OCS node
|
||||
* @param parser
|
||||
* @return reason for exception
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private String readError (XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
String errorMessage = "";
|
||||
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR);
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getName();
|
||||
// read NODE_MESSAGE
|
||||
if (name.equalsIgnoreCase(NODE_MESSAGE)) {
|
||||
errorMessage = readText(parser);
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip tags in parser procedure
|
||||
* @param parser
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int depth = 1;
|
||||
while (depth != 0) {
|
||||
switch (parser.next()) {
|
||||
case XmlPullParser.END_TAG:
|
||||
depth--;
|
||||
break;
|
||||
case XmlPullParser.START_TAG:
|
||||
depth++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the text from a node
|
||||
* @param parser
|
||||
* @return Text of the node
|
||||
* @throws IOException
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||
String result = "";
|
||||
if (parser.next() == XmlPullParser.TEXT) {
|
||||
result = parser.getText();
|
||||
parser.nextTag();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.operations;
|
||||
|
||||
import android.util.Xml;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Parser for Invalid Character server exception
|
||||
* @author masensio
|
||||
*/
|
||||
public class InvalidCharacterExceptionParser {
|
||||
|
||||
private static final String EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath";
|
||||
private static final String EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException";
|
||||
|
||||
// No namespaces
|
||||
private static final String ns = null;
|
||||
|
||||
// Nodes for XML Parser
|
||||
private static final String NODE_ERROR = "d:error";
|
||||
private static final String NODE_EXCEPTION = "s:exception";
|
||||
/**
|
||||
* Parse is as an Invalid Path Exception
|
||||
* @param is
|
||||
* @return if The exception is an Invalid Char Exception
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean parseXMLResponse(InputStream is) throws XmlPullParserException,
|
||||
IOException {
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
// XMLPullParser
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||
parser.setInput(is, null);
|
||||
parser.nextTag();
|
||||
result = readError(parser);
|
||||
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse OCS node
|
||||
* @param parser
|
||||
* @return List of ShareRemoteFiles
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean readError (XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
String exception = "";
|
||||
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR);
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getName();
|
||||
// read NODE_EXCEPTION
|
||||
if (name.equalsIgnoreCase(NODE_EXCEPTION)) {
|
||||
exception = readText(parser);
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
|
||||
}
|
||||
return exception.equalsIgnoreCase(EXCEPTION_STRING) ||
|
||||
exception.equalsIgnoreCase(EXCEPTION_UPLOAD_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip tags in parser procedure
|
||||
* @param parser
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int depth = 1;
|
||||
while (depth != 0) {
|
||||
switch (parser.next()) {
|
||||
case XmlPullParser.END_TAG:
|
||||
depth--;
|
||||
break;
|
||||
case XmlPullParser.START_TAG:
|
||||
depth++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the text from a node
|
||||
* @param parser
|
||||
* @return Text of the node
|
||||
* @throws IOException
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||
String result = "";
|
||||
if (parser.next() == XmlPullParser.TEXT) {
|
||||
result = parser.getText();
|
||||
parser.nextTag();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.operations;
|
||||
|
||||
|
||||
public interface OnRemoteOperationListener {
|
||||
|
||||
void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.operations;
|
||||
|
||||
public class OperationCancelledException extends Exception {
|
||||
|
||||
/**
|
||||
* Generated serial version - to avoid Java warning
|
||||
*/
|
||||
private static final long serialVersionUID = -6350981497740424983L;
|
||||
|
||||
}
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
package com.owncloud.android.lib.common.operations;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountsException;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudAccount;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public abstract class RemoteOperation<T extends Object> implements Runnable {
|
||||
|
||||
private static final String TAG = RemoteOperation.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* OCS API header name
|
||||
*/
|
||||
public static final String OCS_API_HEADER = "OCS-APIREQUEST";
|
||||
|
||||
/**
|
||||
* OCS API header value
|
||||
*/
|
||||
public static final String OCS_API_HEADER_VALUE = "true";
|
||||
|
||||
/**
|
||||
* ownCloud account in the remote ownCloud server to operate
|
||||
*/
|
||||
protected Account mAccount = null;
|
||||
|
||||
/**
|
||||
* Android Application context
|
||||
*/
|
||||
protected Context mContext = null;
|
||||
|
||||
/**
|
||||
* Object to interact with the remote server
|
||||
*/
|
||||
protected OwnCloudClient mClient = null;
|
||||
|
||||
/**
|
||||
* Object to interact with the remote server
|
||||
*/
|
||||
protected OkHttpClient mHttpClient = null;
|
||||
|
||||
/**
|
||||
* Callback object to notify about the execution of the remote operation
|
||||
*/
|
||||
protected OnRemoteOperationListener mListener = null;
|
||||
|
||||
/**
|
||||
* Handler to the thread where mListener methods will be called
|
||||
*/
|
||||
protected Handler mListenerHandler = null;
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available,
|
||||
* instead of {@link #execute(OwnCloudClient, OnRemoteOperationListener, Handler))}.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @param listenerHandler Handler associated to the thread where the methods of the listener
|
||||
* objects must be called.
|
||||
* @return Thread were the remote operation is executed.
|
||||
*/
|
||||
public Thread execute(Account account, Context context,
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
|
||||
if (account == null)
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL Account");
|
||||
if (context == null)
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL Context");
|
||||
// mAccount and mContext in the runnerThread to create below
|
||||
mAccount = account;
|
||||
mContext = context.getApplicationContext();
|
||||
mClient = null; // the client instance will be created from
|
||||
|
||||
mListener = listener;
|
||||
|
||||
mListenerHandler = listenerHandler;
|
||||
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server
|
||||
* during the execution of the operation.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @param listenerHandler Handler, if passed in, associated to the thread where the methods of
|
||||
* the listener objects must be called.
|
||||
* @return Thread were the remote operation is executed.
|
||||
*/
|
||||
public Thread execute(OwnCloudClient client,
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
}
|
||||
mClient = client;
|
||||
if (client.getAccount() != null) {
|
||||
mAccount = client.getAccount().getSavedAccount();
|
||||
}
|
||||
mContext = client.getContext();
|
||||
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation asynchronously " +
|
||||
"without a listener to notiy the result");
|
||||
}
|
||||
mListener = listener;
|
||||
|
||||
if (listenerHandler != null) {
|
||||
mListenerHandler = listenerHandler;
|
||||
}
|
||||
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
protected void grantOwnCloudClient() throws
|
||||
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
||||
if (mClient == null) {
|
||||
if (mAccount != null && mContext != null) {
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
getClientFor(ocAccount, mContext);
|
||||
} else {
|
||||
throw new IllegalStateException("Trying to run a remote operation " +
|
||||
"asynchronously with no client and no chance to create one (no account)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current client instance to access the remote server.
|
||||
*
|
||||
* @return Current client instance to access the remote server.
|
||||
*/
|
||||
public final OwnCloudClient getClient() {
|
||||
return mClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method to implement the operation in derived classes.
|
||||
*/
|
||||
protected abstract RemoteOperationResult<T> run(OwnCloudClient client);
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation on the received ownCloud account.
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available, instead of
|
||||
* {@link #execute(OwnCloudClient)}.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(Account account, Context context) {
|
||||
if (account == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"Account");
|
||||
if (context == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"Context");
|
||||
mAccount = account;
|
||||
mContext = context.getApplicationContext();
|
||||
|
||||
return runOperation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server during the execution of
|
||||
* the operation.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(OwnCloudClient client) {
|
||||
if (client == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
mClient = client;
|
||||
if (client.getAccount() != null) {
|
||||
mAccount = client.getAccount().getSavedAccount();
|
||||
}
|
||||
mContext = client.getContext();
|
||||
|
||||
return runOperation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server during the execution of
|
||||
* the operation.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult<T> execute(OkHttpClient client, Context context) {
|
||||
if (client == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
mHttpClient = client;
|
||||
mContext = context;
|
||||
|
||||
return runOperation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run operation for asynchronous or synchronous 'onExecute' method.
|
||||
*
|
||||
* Considers and performs silent refresh of account credentials if possible, and if
|
||||
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
|
||||
* parameter 'true' before the execution.
|
||||
*
|
||||
* @return Remote operation result
|
||||
*/
|
||||
private RemoteOperationResult<T> runOperation() {
|
||||
|
||||
RemoteOperationResult<T> result;
|
||||
|
||||
try {
|
||||
grantOwnCloudClient();
|
||||
result = run(mClient);
|
||||
|
||||
} catch (AccountsException | IOException e) {
|
||||
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
||||
result = new RemoteOperationResult<>(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous execution of the operation
|
||||
* started by {@link RemoteOperation#execute(OwnCloudClient,
|
||||
* OnRemoteOperationListener, Handler)},
|
||||
* and result posting.
|
||||
*/
|
||||
@Override
|
||||
public final void run() {
|
||||
|
||||
final RemoteOperationResult resultToSend = runOperation();
|
||||
|
||||
if (mAccount != null && mContext != null) {
|
||||
// Save Client Cookies
|
||||
AccountUtils.saveClient(mClient, mAccount, mContext);
|
||||
}
|
||||
|
||||
if (mListenerHandler != null && mListener != null) {
|
||||
mListenerHandler.post(() ->
|
||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend));
|
||||
} else if (mListener != null) {
|
||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
||||
}
|
||||
}
|
||||
}
|
||||
+586
@@ -0,0 +1,586 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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.operations;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountsException;
|
||||
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
||||
import at.bitfire.dav4android.exception.DavException;
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import okhttp3.Headers;
|
||||
|
||||
public class RemoteOperationResult<T extends Object>
|
||||
implements Serializable {
|
||||
|
||||
/**
|
||||
* Generated - should be refreshed every time the class changes!!
|
||||
*/
|
||||
private static final long serialVersionUID = 4968939884332372230L;
|
||||
|
||||
private static final String TAG = RemoteOperationResult.class.getSimpleName();
|
||||
|
||||
public enum ResultCode {
|
||||
OK,
|
||||
OK_SSL,
|
||||
OK_NO_SSL,
|
||||
UNHANDLED_HTTP_CODE,
|
||||
UNAUTHORIZED,
|
||||
FILE_NOT_FOUND,
|
||||
INSTANCE_NOT_CONFIGURED,
|
||||
UNKNOWN_ERROR,
|
||||
WRONG_CONNECTION,
|
||||
TIMEOUT,
|
||||
INCORRECT_ADDRESS,
|
||||
HOST_NOT_AVAILABLE,
|
||||
NO_NETWORK_CONNECTION,
|
||||
SSL_ERROR,
|
||||
SSL_RECOVERABLE_PEER_UNVERIFIED,
|
||||
BAD_OC_VERSION,
|
||||
CANCELLED,
|
||||
INVALID_LOCAL_FILE_NAME,
|
||||
INVALID_OVERWRITE,
|
||||
CONFLICT,
|
||||
OAUTH2_ERROR,
|
||||
SYNC_CONFLICT,
|
||||
LOCAL_STORAGE_FULL,
|
||||
LOCAL_STORAGE_NOT_MOVED,
|
||||
LOCAL_STORAGE_NOT_COPIED,
|
||||
OAUTH2_ERROR_ACCESS_DENIED,
|
||||
QUOTA_EXCEEDED,
|
||||
ACCOUNT_NOT_FOUND,
|
||||
ACCOUNT_EXCEPTION,
|
||||
ACCOUNT_NOT_NEW,
|
||||
ACCOUNT_NOT_THE_SAME,
|
||||
INVALID_CHARACTER_IN_NAME,
|
||||
SHARE_NOT_FOUND,
|
||||
LOCAL_STORAGE_NOT_REMOVED,
|
||||
FORBIDDEN,
|
||||
SHARE_FORBIDDEN,
|
||||
SPECIFIC_FORBIDDEN,
|
||||
OK_REDIRECT_TO_NON_SECURE_CONNECTION,
|
||||
INVALID_MOVE_INTO_DESCENDANT,
|
||||
INVALID_COPY_INTO_DESCENDANT,
|
||||
PARTIAL_MOVE_DONE,
|
||||
PARTIAL_COPY_DONE,
|
||||
SHARE_WRONG_PARAMETER,
|
||||
WRONG_SERVER_RESPONSE,
|
||||
INVALID_CHARACTER_DETECT_IN_SERVER,
|
||||
DELAYED_FOR_WIFI,
|
||||
LOCAL_FILE_NOT_FOUND,
|
||||
SERVICE_UNAVAILABLE,
|
||||
SPECIFIC_SERVICE_UNAVAILABLE,
|
||||
SPECIFIC_UNSUPPORTED_MEDIA_TYPE,
|
||||
SPECIFIC_METHOD_NOT_ALLOWED
|
||||
}
|
||||
|
||||
private boolean mSuccess = false;
|
||||
private int mHttpCode = -1;
|
||||
private String mHttpPhrase = null;
|
||||
private Exception mException = null;
|
||||
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
|
||||
private String mRedirectedLocation;
|
||||
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
||||
private String mLastPermanentLocation = null;
|
||||
private T mData = null;
|
||||
|
||||
/**
|
||||
* Public constructor from result code.
|
||||
*
|
||||
* To be used when the caller takes the responsibility of interpreting the result of a {@link RemoteOperation}
|
||||
*
|
||||
* @param code {@link ResultCode} decided by the caller.
|
||||
*/
|
||||
public RemoteOperationResult(ResultCode code) {
|
||||
mCode = code;
|
||||
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL ||
|
||||
code == ResultCode.OK_NO_SSL ||
|
||||
code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RemoteOperationResult based on the result given by a previous one.
|
||||
* It does not copy the data.
|
||||
* @param prevRemoteOperation
|
||||
*/
|
||||
public RemoteOperationResult(RemoteOperationResult prevRemoteOperation) {
|
||||
mCode = prevRemoteOperation.mCode;
|
||||
mHttpCode = prevRemoteOperation.mHttpCode;
|
||||
mHttpPhrase = prevRemoteOperation.mHttpPhrase;
|
||||
mAuthenticate = prevRemoteOperation.mAuthenticate;
|
||||
mException = prevRemoteOperation.mException;
|
||||
mLastPermanentLocation = prevRemoteOperation.mLastPermanentLocation;
|
||||
mSuccess = prevRemoteOperation.mSuccess;
|
||||
mRedirectedLocation = prevRemoteOperation.mRedirectedLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor from exception.
|
||||
*
|
||||
* To be used when an exception prevented the end of the {@link RemoteOperation}.
|
||||
*
|
||||
* Determines a {@link ResultCode} depending on the type of the exception.
|
||||
*
|
||||
* @param e Exception that interrupted the {@link RemoteOperation}
|
||||
*/
|
||||
public RemoteOperationResult(Exception e) {
|
||||
mException = e;
|
||||
|
||||
if (e instanceof OperationCancelledException) {
|
||||
mCode = ResultCode.CANCELLED;
|
||||
|
||||
} else if (e instanceof SocketException) {
|
||||
mCode = ResultCode.WRONG_CONNECTION;
|
||||
|
||||
} else if (e instanceof SocketTimeoutException) {
|
||||
mCode = ResultCode.TIMEOUT;
|
||||
|
||||
} else if (e instanceof MalformedURLException) {
|
||||
mCode = ResultCode.INCORRECT_ADDRESS;
|
||||
|
||||
} else if (e instanceof UnknownHostException) {
|
||||
mCode = ResultCode.HOST_NOT_AVAILABLE;
|
||||
|
||||
} else if (e instanceof AccountUtils.AccountNotFoundException) {
|
||||
mCode = ResultCode.ACCOUNT_NOT_FOUND;
|
||||
|
||||
} else if (e instanceof AccountsException) {
|
||||
mCode = ResultCode.ACCOUNT_EXCEPTION;
|
||||
|
||||
} else if (e instanceof SSLException || e instanceof RuntimeException) {
|
||||
if(e instanceof SSLPeerUnverifiedException) {
|
||||
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||
} else {
|
||||
CertificateCombinedException se = getCertificateCombinedException(e);
|
||||
if (se != null) {
|
||||
mException = se;
|
||||
if (se.isRecoverable()) {
|
||||
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||
}
|
||||
} else if (e instanceof RuntimeException) {
|
||||
mCode = ResultCode.HOST_NOT_AVAILABLE;
|
||||
|
||||
} else {
|
||||
mCode = ResultCode.SSL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (e instanceof FileNotFoundException) {
|
||||
mCode = ResultCode.LOCAL_FILE_NOT_FOUND;
|
||||
|
||||
} else {
|
||||
mCode = ResultCode.UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor from separate elements of an HTTP or DAV response.
|
||||
*
|
||||
* To be used when the result needs to be interpreted from the response of an HTTP/DAV method.
|
||||
*
|
||||
* Determines a {@link ResultCode} from the already executed method received as a parameter. Generally,
|
||||
* will depend on the HTTP code and HTTP response headers received. In some cases will inspect also the
|
||||
* response body
|
||||
*
|
||||
* @param httpMethod
|
||||
* @throws IOException
|
||||
*/
|
||||
public RemoteOperationResult(HttpBaseMethod httpMethod) throws IOException {
|
||||
this(httpMethod.getStatusCode(),
|
||||
httpMethod.getStatusMessage(),
|
||||
httpMethod.getResponseHeaders()
|
||||
);
|
||||
|
||||
if (mHttpCode == HttpConstants.HTTP_BAD_REQUEST) { // 400
|
||||
String bodyResponse = httpMethod.getResponseBodyAsString();
|
||||
|
||||
// do not get for other HTTP codes!; could not be available
|
||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||
InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
|
||||
try {
|
||||
if (xmlParser.parseXMLResponse(is)) {
|
||||
mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||
// mCode stays as set in this(success, httpCode, headers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// before
|
||||
switch (mHttpCode) {
|
||||
case HttpConstants.HTTP_FORBIDDEN:
|
||||
parseErrorMessageAndSetCode(
|
||||
httpMethod.getResponseBodyAsString(),
|
||||
ResultCode.SPECIFIC_FORBIDDEN
|
||||
);
|
||||
break;
|
||||
case HttpConstants.HTTP_UNSUPPORTED_MEDIA_TYPE:
|
||||
parseErrorMessageAndSetCode(
|
||||
httpMethod.getResponseBodyAsString(),
|
||||
ResultCode.SPECIFIC_UNSUPPORTED_MEDIA_TYPE
|
||||
);
|
||||
break;
|
||||
case HttpConstants.HTTP_SERVICE_UNAVAILABLE:
|
||||
parseErrorMessageAndSetCode(
|
||||
httpMethod.getResponseBodyAsString(),
|
||||
ResultCode.SPECIFIC_SERVICE_UNAVAILABLE
|
||||
);
|
||||
break;
|
||||
case HttpConstants.HTTP_METHOD_NOT_ALLOWED:
|
||||
parseErrorMessageAndSetCode(
|
||||
httpMethod.getResponseBodyAsString(),
|
||||
ResultCode.SPECIFIC_METHOD_NOT_ALLOWED
|
||||
);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the error message included in the body response, if any, and set the specific result
|
||||
* code
|
||||
*
|
||||
* @param bodyResponse okHttp response body
|
||||
* @param resultCode our own custom result code
|
||||
* @throws IOException
|
||||
*/
|
||||
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
|
||||
|
||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||
ErrorMessageParser xmlParser = new ErrorMessageParser();
|
||||
try {
|
||||
String errorMessage = xmlParser.parseXMLResponse(is);
|
||||
if (errorMessage != "" && errorMessage != null) {
|
||||
mCode = resultCode;
|
||||
mHttpPhrase = errorMessage;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||
// mCode stays as set in this(success, httpCode, headers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor from separate elements of an HTTP or DAV response.
|
||||
*
|
||||
* To be used when the result needs to be interpreted from HTTP response elements that could come from
|
||||
* different requests (WARNING: black magic, try to avoid).
|
||||
*
|
||||
*
|
||||
* Determines a {@link ResultCode} depending on the HTTP code and HTTP response headers received.
|
||||
*
|
||||
* @param httpCode HTTP status code returned by an HTTP/DAV method.
|
||||
* @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method
|
||||
* @param headers HTTP response header returned by an HTTP/DAV method
|
||||
*/
|
||||
public RemoteOperationResult(int httpCode, String httpPhrase, Headers headers) {
|
||||
this(httpCode, httpPhrase);
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, List<String>> header : headers.toMultimap().entrySet()) {
|
||||
if ("location".equals(header.getKey().toLowerCase())) {
|
||||
mRedirectedLocation = header.getValue().get(0);
|
||||
continue;
|
||||
}
|
||||
if ("www-authenticate".equals(header.getKey().toLowerCase())) {
|
||||
mAuthenticate.add(header.getValue().get(0).toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isIdPRedirection()) {
|
||||
// overrides default ResultCode.UNKNOWN
|
||||
mCode = ResultCode.UNAUTHORIZED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for results built interpreting a HTTP or DAV response.
|
||||
*
|
||||
* Determines a {@link ResultCode} depending of the type of the exception.
|
||||
*
|
||||
* @param httpCode HTTP status code returned by the HTTP/DAV method.
|
||||
* @param httpPhrase HTTP status line phrase returned by the HTTP/DAV method
|
||||
*/
|
||||
private RemoteOperationResult(int httpCode, String httpPhrase) {
|
||||
mHttpCode = httpCode;
|
||||
mHttpPhrase = httpPhrase;
|
||||
|
||||
if (httpCode > 0) {
|
||||
switch (httpCode) {
|
||||
case HttpConstants.HTTP_UNAUTHORIZED: // 401
|
||||
mCode = ResultCode.UNAUTHORIZED;
|
||||
break;
|
||||
case HttpConstants.HTTP_FORBIDDEN: // 403
|
||||
mCode = ResultCode.FORBIDDEN;
|
||||
break;
|
||||
case HttpConstants.HTTP_NOT_FOUND: // 404
|
||||
mCode = ResultCode.FILE_NOT_FOUND;
|
||||
break;
|
||||
case HttpConstants.HTTP_CONFLICT: // 409
|
||||
mCode = ResultCode.CONFLICT;
|
||||
break;
|
||||
case HttpConstants.HTTP_INTERNAL_SERVER_ERROR: // 500
|
||||
mCode = ResultCode.INSTANCE_NOT_CONFIGURED; // assuming too much...
|
||||
break;
|
||||
case HttpConstants.HTTP_SERVICE_UNAVAILABLE: // 503
|
||||
mCode = ResultCode.SERVICE_UNAVAILABLE;
|
||||
break;
|
||||
case HttpConstants.HTTP_INSUFFICIENT_STORAGE: // 507
|
||||
mCode = ResultCode.QUOTA_EXCEEDED; // surprise!
|
||||
break;
|
||||
default:
|
||||
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
||||
Log_OC.d(TAG,
|
||||
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
||||
|
||||
mHttpCode + " " + mHttpPhrase
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isSuccess() {
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return mCode == ResultCode.CANCELLED;
|
||||
}
|
||||
|
||||
public int getHttpCode() {
|
||||
return mHttpCode;
|
||||
}
|
||||
|
||||
public String getHttpPhrase() {
|
||||
return mHttpPhrase;
|
||||
}
|
||||
|
||||
public ResultCode getCode() {
|
||||
return mCode;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return mException;
|
||||
}
|
||||
|
||||
public boolean isSslRecoverableException() {
|
||||
return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||
}
|
||||
|
||||
public boolean isRedirectToNonSecureConnection() {
|
||||
return mCode == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION;
|
||||
}
|
||||
|
||||
private CertificateCombinedException getCertificateCombinedException(Exception e) {
|
||||
CertificateCombinedException result = null;
|
||||
if (e instanceof CertificateCombinedException) {
|
||||
return (CertificateCombinedException) e;
|
||||
}
|
||||
Throwable cause = mException.getCause();
|
||||
Throwable previousCause = null;
|
||||
while (cause != null && cause != previousCause &&
|
||||
!(cause instanceof CertificateCombinedException)) {
|
||||
previousCause = cause;
|
||||
cause = cause.getCause();
|
||||
}
|
||||
if (cause != null && cause instanceof CertificateCombinedException) {
|
||||
result = (CertificateCombinedException) cause;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getLogMessage() {
|
||||
|
||||
if (mException != null) {
|
||||
if (mException instanceof OperationCancelledException) {
|
||||
return "Operation cancelled by the caller";
|
||||
|
||||
} else if (mException instanceof SocketException) {
|
||||
return "Socket exception";
|
||||
|
||||
} else if (mException instanceof SocketTimeoutException) {
|
||||
return "Socket timeout exception";
|
||||
|
||||
} else if (mException instanceof MalformedURLException) {
|
||||
return "Malformed URL exception";
|
||||
|
||||
} else if (mException instanceof UnknownHostException) {
|
||||
return "Unknown host exception";
|
||||
|
||||
} else if (mException instanceof CertificateCombinedException) {
|
||||
if (((CertificateCombinedException) mException).isRecoverable())
|
||||
return "SSL recoverable exception";
|
||||
else
|
||||
return "SSL exception";
|
||||
|
||||
} else if (mException instanceof SSLException) {
|
||||
return "SSL exception";
|
||||
|
||||
} else if (mException instanceof DavException) {
|
||||
return "Unexpected WebDAV exception";
|
||||
|
||||
} else if (mException instanceof HttpException) {
|
||||
return "HTTP violation";
|
||||
|
||||
} else if (mException instanceof IOException) {
|
||||
return "Unrecovered transport exception";
|
||||
|
||||
} else if (mException instanceof AccountUtils.AccountNotFoundException) {
|
||||
Account failedAccount =
|
||||
((AccountUtils.AccountNotFoundException) mException).getFailedAccount();
|
||||
return mException.getMessage() + " (" +
|
||||
(failedAccount != null ? failedAccount.name : "NULL") + ")";
|
||||
|
||||
} else if (mException instanceof AccountsException) {
|
||||
return "Exception while using account";
|
||||
|
||||
} else if (mException instanceof JSONException) {
|
||||
return "JSON exception";
|
||||
|
||||
} else {
|
||||
return "Unexpected exception";
|
||||
}
|
||||
}
|
||||
|
||||
if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
|
||||
return "The ownCloud server is not configured!";
|
||||
|
||||
} else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
|
||||
return "No network connection";
|
||||
|
||||
} else if (mCode == ResultCode.BAD_OC_VERSION) {
|
||||
return "No valid ownCloud version was found at the server";
|
||||
|
||||
} else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
|
||||
return "Local storage full";
|
||||
|
||||
} else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
|
||||
return "Error while moving file to final directory";
|
||||
|
||||
} else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
|
||||
return "Account already existing when creating a new one";
|
||||
|
||||
} else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
|
||||
return "Authenticated with a different account than the one updating";
|
||||
|
||||
} else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
|
||||
return "The file name contains an forbidden character";
|
||||
|
||||
} else if (mCode == ResultCode.FILE_NOT_FOUND) {
|
||||
return "Local file does not exist";
|
||||
|
||||
} else if (mCode == ResultCode.SYNC_CONFLICT) {
|
||||
return "Synchronization conflict";
|
||||
}
|
||||
|
||||
return "Operation finished with HTTP status code " + mHttpCode + " (" +
|
||||
(isSuccess() ? "success" : "fail") + ")";
|
||||
|
||||
}
|
||||
|
||||
public boolean isServerFail() {
|
||||
return (mHttpCode >= HttpConstants.HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
public boolean isException() {
|
||||
return (mException != null);
|
||||
}
|
||||
|
||||
public boolean isTemporalRedirection() {
|
||||
return (mHttpCode == 302 || mHttpCode == 307);
|
||||
}
|
||||
|
||||
public String getRedirectedLocation() {
|
||||
return mRedirectedLocation;
|
||||
}
|
||||
|
||||
public boolean isIdPRedirection() {
|
||||
return (mRedirectedLocation != null &&
|
||||
(mRedirectedLocation.toUpperCase().contains("SAML") ||
|
||||
mRedirectedLocation.toLowerCase().contains("wayf")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is a non https connection
|
||||
*
|
||||
* @return boolean true/false
|
||||
*/
|
||||
public boolean isNonSecureRedirection() {
|
||||
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
|
||||
}
|
||||
|
||||
public ArrayList<String> getAuthenticateHeaders() {
|
||||
return mAuthenticate;
|
||||
}
|
||||
|
||||
public String getLastPermanentLocation() {
|
||||
return mLastPermanentLocation;
|
||||
}
|
||||
|
||||
public void setLastPermanentLocation(String lastPermanentLocation) {
|
||||
mLastPermanentLocation = lastPermanentLocation;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.mSuccess = success;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
mData = data;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return mData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package com.owncloud.android.lib.common.utils;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Log_OC {
|
||||
private static final String SIMPLE_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
|
||||
private static final String LOG_FOLDER_NAME = "log";
|
||||
private static final long MAX_FILE_SIZE = 1000000; // 1MB
|
||||
|
||||
private static String mOwncloudDataFolderLog = "owncloud_log";
|
||||
|
||||
private static File mLogFile;
|
||||
private static File mFolder;
|
||||
private static BufferedWriter mBuf;
|
||||
|
||||
private static String[] mLogFileNames = {"currentLog.txt", "olderLog.txt"};
|
||||
|
||||
private static boolean isMaxFileSizeReached = false;
|
||||
private static boolean isEnabled = false;
|
||||
|
||||
public static void setLogDataFolder(String logFolder){
|
||||
mOwncloudDataFolderLog = logFolder;
|
||||
}
|
||||
|
||||
public static void i(String TAG, String message){
|
||||
Log.i(TAG, message);
|
||||
appendLog(TAG+" : "+ message);
|
||||
}
|
||||
|
||||
public static void d(String TAG, String message){
|
||||
Log.d(TAG, message);
|
||||
appendLog(TAG + " : " + message);
|
||||
}
|
||||
public static void d(String TAG, String message, Exception e) {
|
||||
Log.d(TAG, message, e);
|
||||
appendLog(TAG + " : " + message + " Exception : "+ e.getStackTrace());
|
||||
}
|
||||
public static void e(String TAG, String message){
|
||||
Log.e(TAG, message);
|
||||
appendLog(TAG + " : " + message);
|
||||
}
|
||||
|
||||
public static void e(String TAG, String message, Throwable e) {
|
||||
Log.e(TAG, message, e);
|
||||
appendLog(TAG+" : " + message +" Exception : " + e.getStackTrace());
|
||||
}
|
||||
|
||||
public static void v(String TAG, String message){
|
||||
Log.v(TAG, message);
|
||||
appendLog(TAG+" : "+ message);
|
||||
}
|
||||
|
||||
public static void w(String TAG, String message) {
|
||||
Log.w(TAG, message);
|
||||
appendLog(TAG+" : "+ message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start doing logging
|
||||
* @param storagePath : directory for keeping logs
|
||||
*/
|
||||
synchronized public static void startLogging(String storagePath) {
|
||||
String logPath = storagePath + File.separator +
|
||||
mOwncloudDataFolderLog + File.separator + LOG_FOLDER_NAME;
|
||||
mFolder = new File(logPath);
|
||||
mLogFile = new File(mFolder + File.separator + mLogFileNames[0]);
|
||||
|
||||
boolean isFileCreated = false;
|
||||
|
||||
if (!mFolder.exists()) {
|
||||
mFolder.mkdirs();
|
||||
isFileCreated = true;
|
||||
Log.d("LOG_OC", "Log file created");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Create the current log file if does not exist
|
||||
mLogFile.createNewFile();
|
||||
mBuf = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||
isEnabled = true;
|
||||
|
||||
if (isFileCreated) {
|
||||
appendPhoneInfo();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(mBuf != null) {
|
||||
try {
|
||||
mBuf.close();
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public static void stopLogging() {
|
||||
try {
|
||||
if (mBuf != null)
|
||||
mBuf.close();
|
||||
isEnabled = false;
|
||||
|
||||
mLogFile = null;
|
||||
mFolder = null;
|
||||
mBuf = null;
|
||||
isMaxFileSizeReached = false;
|
||||
isEnabled = false;
|
||||
|
||||
} catch (IOException e) {
|
||||
// Because we are stopping logging, we only log to Android console.
|
||||
Log.e("OC_Log", "Closing log file failed: ", e);
|
||||
} catch (Exception e) {
|
||||
// This catch should never fire because we do null check on mBuf.
|
||||
// But just for the sake of stability let's log this odd situation.
|
||||
// Because we are stopping logging, we only log to Android console.
|
||||
Log.e("OC_Log", "Stopping logging failed: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete history logging
|
||||
*/
|
||||
public static void deleteHistoryLogging() {
|
||||
File folderLogs = new File(mFolder + File.separator);
|
||||
if(folderLogs.isDirectory()){
|
||||
String[] myFiles = folderLogs.list();
|
||||
for (int i=0; i<myFiles.length; i++) {
|
||||
File myFile = new File(folderLogs, myFiles[i]);
|
||||
myFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the info of the device
|
||||
*/
|
||||
private static void appendPhoneInfo() {
|
||||
appendLog("Model : " + android.os.Build.MODEL);
|
||||
appendLog("Brand : " + android.os.Build.BRAND);
|
||||
appendLog("Product : " + android.os.Build.PRODUCT);
|
||||
appendLog("Device : " + android.os.Build.DEVICE);
|
||||
appendLog("Version-Codename : " + android.os.Build.VERSION.CODENAME);
|
||||
appendLog("Version-Release : " + android.os.Build.VERSION.RELEASE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append to the log file the info passed
|
||||
* @param text : text for adding to the log file
|
||||
*/
|
||||
synchronized private static void appendLog(String text) {
|
||||
|
||||
if (isEnabled) {
|
||||
|
||||
if (isMaxFileSizeReached) {
|
||||
|
||||
// Move current log file info to another file (old logs)
|
||||
File olderFile = new File(mFolder + File.separator + mLogFileNames[1]);
|
||||
if (mLogFile.exists()) {
|
||||
mLogFile.renameTo(olderFile);
|
||||
}
|
||||
|
||||
// Construct a new file for current log info
|
||||
mLogFile = new File(mFolder + File.separator + mLogFileNames[0]);
|
||||
isMaxFileSizeReached = false;
|
||||
}
|
||||
|
||||
String timeStamp = new SimpleDateFormat(SIMPLE_DATE_FORMAT).format(Calendar.getInstance().getTime());
|
||||
|
||||
try {
|
||||
mBuf = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||
mBuf.newLine();
|
||||
mBuf.write(timeStamp);
|
||||
mBuf.newLine();
|
||||
mBuf.write(text);
|
||||
mBuf.newLine();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
mBuf.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if current log file size is bigger than the max file size defined
|
||||
if (mLogFile.length() > MAX_FILE_SIZE) {
|
||||
isMaxFileSizeReached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getLogFileNames() {
|
||||
return mLogFileNames;
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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.utils;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Class with methods to generate random values
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class RandomUtils {
|
||||
|
||||
private static final String CANDIDATECHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||
"1234567890-+/_=.:";
|
||||
|
||||
/**
|
||||
* @param length the number of random chars to be generated
|
||||
*
|
||||
* @return String containing random chars
|
||||
*/
|
||||
public static String generateRandomString(int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(CANDIDATECHARS.charAt(random.nextInt(CANDIDATECHARS.length())));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param min minimum integer to obtain randomly
|
||||
* @param max maximum integer to obtain randomly
|
||||
* @return random integer between min and max
|
||||
*/
|
||||
public static int generateRandomInteger(int min, int max) {
|
||||
Random r = new Random();
|
||||
return r.nextInt(max-min) + min;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return random UUID
|
||||
*/
|
||||
public static String generateRandomUUID() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||
* in the same account.
|
||||
*
|
||||
* Allows renaming the moving file/folder at the same time.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
public class CopyRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = CopyRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int COPY_READ_TIMEOUT = 600000;
|
||||
private static final int COPY_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private String mSrcRemotePath;
|
||||
private String mTargetRemotePath;
|
||||
|
||||
private boolean mOverwrite;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* <p/>
|
||||
* TODO Paths should finish in "/" in the case of folders. ?
|
||||
*
|
||||
* @param srcRemotePath Remote path of the file/folder to move.
|
||||
* @param targetRemotePath Remove path desired for the file/folder after moving it.
|
||||
*/
|
||||
public CopyRemoteFileOperation(String srcRemotePath, String targetRemotePath, boolean overwrite
|
||||
) {
|
||||
mSrcRemotePath = srcRemotePath;
|
||||
mTargetRemotePath = targetRemotePath;
|
||||
mOverwrite = overwrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the rename operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
/// check parameters
|
||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||
// nothing to do!
|
||||
return new RemoteOperationResult<>(ResultCode.OK);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_COPY_INTO_DESCENDANT);
|
||||
}
|
||||
|
||||
/// perform remote operation
|
||||
RemoteOperationResult result = null;
|
||||
try {
|
||||
CopyMethod copyMethod = new CopyMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||
client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
||||
mOverwrite);
|
||||
|
||||
copyMethod.setReadTimeout(COPY_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
copyMethod.setConnectionTimeout(COPY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
final int status = client.executeHttpMethod(copyMethod);
|
||||
|
||||
if(status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT) {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
|
||||
|
||||
result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||
|
||||
|
||||
/// for other errors that could be explicitly handled, check first:
|
||||
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(copyMethod);
|
||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
Log.i(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.MkColMethod;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* Remote operation performing the creation of a new folder in the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
*/
|
||||
public class CreateRemoteFolderOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = CreateRemoteFolderOperation.class.getSimpleName();
|
||||
|
||||
private static final int READ_TIMEOUT = 30000;
|
||||
private static final int CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private String mRemotePath;
|
||||
private boolean mCreateFullPath;
|
||||
protected boolean createChunksFolder;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param remotePath Full path to the new directory to create in the remote server.
|
||||
* @param createFullPath 'True' means that all the ancestor folders should be created.
|
||||
*/
|
||||
public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
|
||||
mRemotePath = remotePath;
|
||||
mCreateFullPath = createFullPath;
|
||||
createChunksFolder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the operation
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars);
|
||||
if (noInvalidChars) {
|
||||
result = createFolder(client);
|
||||
if (!result.isSuccess() && mCreateFullPath &&
|
||||
RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) {
|
||||
result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
|
||||
if (result.isSuccess()) {
|
||||
result = createFolder(client); // second (and last) try
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private RemoteOperationResult createFolder(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
try {
|
||||
Uri webDavUri = createChunksFolder ? client.getUploadsWebDavUri() : client.getUserFilesWebDavUri();
|
||||
final MkColMethod mkcol = new MkColMethod(new URL(webDavUri + WebdavUtils.encodePath(mRemotePath)));
|
||||
mkcol.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
mkcol.setConnectionTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
final int status = client.executeHttpMethod(mkcol);
|
||||
|
||||
result = (status == HttpConstants.HTTP_CREATED)
|
||||
? new RemoteOperationResult<>(ResultCode.OK)
|
||||
: new RemoteOperationResult<>(mkcol);
|
||||
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private RemoteOperationResult createParentFolder(String parentPath, OwnCloudClient client) {
|
||||
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath, mCreateFullPath);
|
||||
return operation.execute(client);
|
||||
}
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Remote operation performing the download of a remote file in the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
*/
|
||||
|
||||
public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName();
|
||||
private static final int FORBIDDEN_ERROR = 403;
|
||||
private static final int SERVICE_UNAVAILABLE_ERROR = 503;
|
||||
|
||||
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
private long mModificationTimestamp = 0;
|
||||
private String mEtag = "";
|
||||
private GetMethod mGet;
|
||||
|
||||
private String mRemotePath;
|
||||
private String mLocalFolderPath;
|
||||
|
||||
public DownloadRemoteFileOperation(String remotePath, String localFolderPath) {
|
||||
mRemotePath = remotePath;
|
||||
mLocalFolderPath = localFolderPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
||||
/// download will be performed to a temporal file, then moved to the final location
|
||||
File tmpFile = new File(getTmpPath());
|
||||
|
||||
/// perform the download
|
||||
try {
|
||||
tmpFile.getParentFile().mkdirs();
|
||||
result = downloadFile(client, tmpFile);
|
||||
Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
||||
result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
||||
result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private RemoteOperationResult downloadFile(OwnCloudClient client, File targetFile) throws
|
||||
Exception {
|
||||
|
||||
RemoteOperationResult result;
|
||||
int status;
|
||||
boolean savedFile = false;
|
||||
mGet = new GetMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)));
|
||||
Iterator<OnDatatransferProgressListener> it;
|
||||
|
||||
FileOutputStream fos = null;
|
||||
BufferedInputStream bis = null;
|
||||
try {
|
||||
status = client.executeHttpMethod(mGet);
|
||||
if (isSuccess(status)) {
|
||||
targetFile.createNewFile();
|
||||
bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
|
||||
fos = new FileOutputStream(targetFile);
|
||||
long transferred = 0;
|
||||
|
||||
String contentLength = mGet.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER);
|
||||
long totalToTransfer =
|
||||
(contentLength != null
|
||||
&& contentLength.length() > 0)
|
||||
? Long.parseLong(contentLength)
|
||||
: 0;
|
||||
|
||||
byte[] bytes = new byte[4096];
|
||||
int readResult;
|
||||
while ((readResult = bis.read(bytes)) != -1) {
|
||||
synchronized (mCancellationRequested) {
|
||||
if (mCancellationRequested.get()) {
|
||||
mGet.abort();
|
||||
throw new OperationCancelledException();
|
||||
}
|
||||
}
|
||||
fos.write(bytes, 0, readResult);
|
||||
transferred += readResult;
|
||||
synchronized (mDataTransferListeners) {
|
||||
it = mDataTransferListeners.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next().onTransferProgress(readResult, transferred, totalToTransfer,
|
||||
targetFile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (transferred == totalToTransfer) { // Check if the file is completed
|
||||
savedFile = true;
|
||||
final String modificationTime =
|
||||
mGet.getResponseHeaders().get("Last-Modified") != null
|
||||
? mGet.getResponseHeaders().get("Last-Modified")
|
||||
: mGet.getResponseHeader("last-modified");
|
||||
|
||||
if (modificationTime != null) {
|
||||
final Date d = WebdavUtils.parseResponseDate(modificationTime);
|
||||
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
||||
} else {
|
||||
Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath);
|
||||
}
|
||||
|
||||
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
||||
|
||||
// Get rid of extra quotas
|
||||
mEtag = mEtag.replace("\"", "");
|
||||
|
||||
if (mEtag.length() == 0) {
|
||||
Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath);
|
||||
}
|
||||
|
||||
} else {
|
||||
client.exhaustResponse(mGet.getResponseBodyAsStream());
|
||||
// TODO some kind of error control!
|
||||
}
|
||||
|
||||
} else if (status != FORBIDDEN_ERROR && status != SERVICE_UNAVAILABLE_ERROR) {
|
||||
client.exhaustResponse(mGet.getResponseBodyAsStream());
|
||||
|
||||
} // else, body read by RemoteOperationResult constructor
|
||||
|
||||
result = isSuccess(status)
|
||||
? new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK)
|
||||
: new RemoteOperationResult<>(mGet);
|
||||
} finally {
|
||||
if (fos != null) fos.close();
|
||||
if (bis != null) bis.close();
|
||||
if (!savedFile && targetFile.exists()) {
|
||||
targetFile.delete();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
|
||||
private String getTmpPath() {
|
||||
return mLocalFolderPath + mRemotePath;
|
||||
}
|
||||
|
||||
public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
|
||||
}
|
||||
|
||||
public long getModificationTimestamp() {
|
||||
return mModificationTimestamp;
|
||||
}
|
||||
|
||||
public String getEtag() {
|
||||
return mEtag;
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Operation to check the existence or absence of a path in a remote server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class ExistenceCheckRemoteOperation extends RemoteOperation {
|
||||
|
||||
/**
|
||||
* Maximum time to wait for a response from the server in MILLISECONDs.
|
||||
*/
|
||||
public static final int TIMEOUT = 10000;
|
||||
|
||||
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
|
||||
|
||||
private String mPath;
|
||||
private boolean mSuccessIfAbsent;
|
||||
private boolean mIsLogin;
|
||||
|
||||
/**
|
||||
* Sequence of redirections followed. Available only after executing the operation
|
||||
*/
|
||||
private RedirectionPath mRedirectionPath = null;
|
||||
|
||||
/**
|
||||
* Full constructor. Success of the operation will depend upon the value of successIfAbsent.
|
||||
*
|
||||
* @param remotePath Path to append to the URL owned by the client instance.
|
||||
* @param successIfAbsent When 'true', the operation finishes in success if the path does
|
||||
* NOT exist in the remote server (HTTP 404).
|
||||
* @param isLogin When `true`, the username won't be added at the end of the PROPFIND url since is not
|
||||
* needed to check user credentials
|
||||
*/
|
||||
public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent, boolean isLogin) {
|
||||
mPath = (remotePath != null) ? remotePath : "";
|
||||
mSuccessIfAbsent = successIfAbsent;
|
||||
mIsLogin = isLogin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
boolean previousFollowRedirects = client.followRedirects();
|
||||
|
||||
try {
|
||||
String stringUrl = mIsLogin ?
|
||||
client.getBaseFilesWebDavUri().toString() :
|
||||
client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mPath);
|
||||
PropfindMethod propfindMethod = new PropfindMethod(
|
||||
new URL(stringUrl),
|
||||
0,
|
||||
DavUtils.getAllPropset()
|
||||
);
|
||||
propfindMethod.setReadTimeout(TIMEOUT, TimeUnit.SECONDS);
|
||||
propfindMethod.setConnectionTimeout(TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
client.setFollowRedirects(false);
|
||||
int status = client.executeHttpMethod(propfindMethod);
|
||||
|
||||
if (previousFollowRedirects) {
|
||||
mRedirectionPath = client.followRedirection(propfindMethod);
|
||||
status = mRedirectionPath.getLastStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* PROPFIND method
|
||||
* 404 NOT FOUND: path doesn't exist,
|
||||
* 207 MULTI_STATUS: path exists.
|
||||
*/
|
||||
|
||||
Log_OC.d(TAG, "Existence check for " + stringUrl + WebdavUtils.encodePath(mPath) +
|
||||
" targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") +
|
||||
"finished with HTTP status " + status + (!isSuccess(status) ? "(FAIL)" : ""));
|
||||
|
||||
return isSuccess(status)
|
||||
? new RemoteOperationResult<>(OK)
|
||||
: new RemoteOperationResult<>(propfindMethod);
|
||||
|
||||
} catch (Exception e) {
|
||||
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Existence check for " + client.getUserFilesWebDavUri() +
|
||||
WebdavUtils.encodePath(mPath) + " targeting for " +
|
||||
(mSuccessIfAbsent ? " absence " : " existence ") + ": " +
|
||||
result.getLogMessage(), result.getException());
|
||||
return result;
|
||||
} finally {
|
||||
client.setFollowRedirects(previousFollowRedirects);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sequence of redirections followed during the execution of the operation.
|
||||
*
|
||||
* @return Sequence of redirections followed, if any, or NULL if the operation was not executed.
|
||||
*/
|
||||
public RedirectionPath getRedirectionPath() {
|
||||
return mRedirectionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 'True' if the operation was executed and at least one redirection was followed.
|
||||
*/
|
||||
public boolean wasRedirected() {
|
||||
return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0);
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return ((status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_MULTI_STATUS) && !mSuccessIfAbsent)
|
||||
|| (status == HttpConstants.HTTP_MULTI_STATUS && !mSuccessIfAbsent)
|
||||
|| (status == HttpConstants.HTTP_NOT_FOUND && mSuccessIfAbsent);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
private static final String TAG = FileUtils.class.getSimpleName();
|
||||
|
||||
public static final String PATH_SEPARATOR = "/";
|
||||
public static final String FINAL_CHUNKS_FILE = ".file";
|
||||
|
||||
public static String getParentPath(String remotePath) {
|
||||
String parentPath = new File(remotePath).getParent();
|
||||
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
|
||||
return parentPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the fileName to detect if contains any forbidden character: / , \ , < , > ,
|
||||
* : , " , | , ? , *
|
||||
* @param fileName
|
||||
* @param versionSupportsForbiddenChars
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
|
||||
boolean result = true;
|
||||
|
||||
Log_OC.d(TAG, "fileName =======" + fileName);
|
||||
if ( (versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
|
||||
(!versionSupportsForbiddenChars && ( fileName.contains(PATH_SEPARATOR) ||
|
||||
fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
|
||||
fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
|
||||
fileName.contains("?") || fileName.contains("*") ) ) ) {
|
||||
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | ,
|
||||
* ? , *
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidPath(String path, boolean versionSupportsForbidenChars) {
|
||||
boolean result = true;
|
||||
|
||||
Log_OC.d(TAG, "path ....... " + path);
|
||||
if (!versionSupportsForbidenChars &&
|
||||
(path.contains("\\") || path.contains("<") || path.contains(">") ||
|
||||
path.contains(":") || path.contains("\"") || path.contains("|") ||
|
||||
path.contains("?") || path.contains("*") ) ){
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||
* in the same account.
|
||||
*
|
||||
* Allows renaming the moving file/folder at the same time.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class MoveRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = MoveRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int MOVE_READ_TIMEOUT = 600000;
|
||||
private static final int MOVE_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private String mSrcRemotePath;
|
||||
private String mTargetRemotePath;
|
||||
private boolean mOverwrite;
|
||||
|
||||
protected boolean moveChunkedFile = false;
|
||||
protected String mFileLastModifTimestamp;
|
||||
protected long mFileLength;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* TODO Paths should finish in "/" in the case of folders. ?
|
||||
*
|
||||
* @param srcRemotePath Remote path of the file/folder to move.
|
||||
* @param targetRemotePath Remote path desired for the file/folder after moving it.
|
||||
*/
|
||||
public MoveRemoteFileOperation(String srcRemotePath,
|
||||
String targetRemotePath,
|
||||
boolean overwrite) {
|
||||
|
||||
mSrcRemotePath = srcRemotePath;
|
||||
mTargetRemotePath = targetRemotePath;
|
||||
mOverwrite = overwrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the rename operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
/// check parameters
|
||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||
// nothing to do!
|
||||
return new RemoteOperationResult<>(ResultCode.OK);
|
||||
}
|
||||
|
||||
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_MOVE_INTO_DESCENDANT);
|
||||
}
|
||||
|
||||
/// perform remote operation
|
||||
RemoteOperationResult result;
|
||||
try {
|
||||
// After finishing a chunked upload, we have to move the resulting file from uploads folder to files one,
|
||||
// so this uri has to be customizable
|
||||
Uri srcWebDavUri = moveChunkedFile ? client.getUploadsWebDavUri() : client.getUserFilesWebDavUri();
|
||||
|
||||
final MoveMethod move = new MoveMethod(
|
||||
new URL(srcWebDavUri + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||
client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
||||
mOverwrite);
|
||||
|
||||
if (moveChunkedFile) {
|
||||
move.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
||||
move.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(mFileLength));
|
||||
}
|
||||
|
||||
move.setReadTimeout(MOVE_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
move.setConnectionTimeout(MOVE_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
final int status = client.executeHttpMethod(move);
|
||||
/// process response
|
||||
if(isSuccess(status)) {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
|
||||
|
||||
result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||
|
||||
/// for other errors that could be explicitly handled, check first:
|
||||
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(move);
|
||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
Log.i(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isSuccess(int status) {
|
||||
return status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT;
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
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 com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Remote operation performing the read a file from the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
|
||||
|
||||
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
|
||||
private static final int SYNC_READ_TIMEOUT = 40000;
|
||||
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private String mRemotePath;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remotePath Remote path of the file.
|
||||
*/
|
||||
public ReadRemoteFileOperation(String remotePath) {
|
||||
mRemotePath = remotePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the read operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult<RemoteFile> run(OwnCloudClient client) {
|
||||
PropfindMethod propfind;
|
||||
RemoteOperationResult<RemoteFile> result;
|
||||
|
||||
/// take the duty of check the server for the current state of the file there
|
||||
try {
|
||||
// remote request
|
||||
propfind = new PropfindMethod(new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
|
||||
DEPTH_0,
|
||||
DavUtils.getAllPropset());
|
||||
|
||||
propfind.setReadTimeout(SYNC_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
propfind.setConnectionTimeout(SYNC_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
final int status = client.executeHttpMethod(propfind);
|
||||
|
||||
if (status == HttpConstants.HTTP_MULTI_STATUS
|
||||
|| status == HttpConstants.HTTP_OK) {
|
||||
|
||||
final RemoteFile file = new RemoteFile(propfind.getRoot(), AccountUtils.getUserId(mAccount, mContext));
|
||||
|
||||
result = new RemoteOperationResult<>(OK);
|
||||
result.setData(file);
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(propfind);
|
||||
client.exhaustResponse(propfind.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
e.printStackTrace();
|
||||
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
|
||||
result.getException());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||
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.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import at.bitfire.dav4android.Response;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Remote operation performing the read of remote file or folder in the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteFile>> {
|
||||
|
||||
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
|
||||
|
||||
private String mRemotePath;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remotePath Remote path of the file.
|
||||
*/
|
||||
public ReadRemoteFolderOperation(String remotePath) {
|
||||
mRemotePath = remotePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the read operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult<ArrayList<RemoteFile>> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ArrayList<RemoteFile>> result = null;
|
||||
|
||||
try {
|
||||
PropfindMethod propfindMethod = new PropfindMethod(
|
||||
new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
|
||||
DavConstants.DEPTH_1,
|
||||
DavUtils.getAllPropset());
|
||||
|
||||
client.setFollowRedirects(true);
|
||||
|
||||
int status = client.executeHttpMethod(propfindMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
ArrayList<RemoteFile> mFolderAndFiles = new ArrayList<>();
|
||||
|
||||
// parse data from remote folder
|
||||
mFolderAndFiles.add(
|
||||
new RemoteFile(propfindMethod.getRoot(), AccountUtils.getUserId(mAccount, mContext))
|
||||
);
|
||||
|
||||
// loop to update every child
|
||||
for (Response resource : propfindMethod.getMembers()) {
|
||||
RemoteFile file = new RemoteFile(resource, AccountUtils.getUserId(mAccount, mContext));
|
||||
mFolderAndFiles.add(file);
|
||||
}
|
||||
|
||||
// Result of the operation
|
||||
result = new RemoteOperationResult<>(OK);
|
||||
result.setData(mFolderAndFiles);
|
||||
|
||||
} else { // synchronization failed
|
||||
result = new RemoteOperationResult<> (propfindMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
} finally {
|
||||
if (result.isSuccess()) {
|
||||
Log_OC.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
} else {
|
||||
if (result.isException()) {
|
||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(),
|
||||
result.getException());
|
||||
} else {
|
||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return status == HttpConstants.HTTP_MULTI_STATUS ||
|
||||
status == HttpConstants.HTTP_OK;
|
||||
}
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import at.bitfire.dav4android.Property;
|
||||
import at.bitfire.dav4android.Response;
|
||||
import at.bitfire.dav4android.property.CreationDate;
|
||||
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 okhttp3.HttpUrl;
|
||||
|
||||
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0;
|
||||
|
||||
/**
|
||||
* Contains the data of a Remote File from a WebDavEntry
|
||||
*
|
||||
* @author masensio
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
|
||||
public class RemoteFile implements Parcelable, Serializable {
|
||||
|
||||
/**
|
||||
* Generated - should be refreshed every time the class changes!!
|
||||
*/
|
||||
private static final long serialVersionUID = -8965995357413958539L;
|
||||
|
||||
private String mRemotePath;
|
||||
private String mMimeType;
|
||||
private long mLength;
|
||||
private long mCreationTimestamp;
|
||||
private long mModifiedTimestamp;
|
||||
private String mEtag;
|
||||
private String mPermissions;
|
||||
private String mRemoteId;
|
||||
private long mSize;
|
||||
private BigDecimal mQuotaUsedBytes;
|
||||
private BigDecimal mQuotaAvailableBytes;
|
||||
private String mPrivateLink;
|
||||
|
||||
/**
|
||||
* Getters and Setters
|
||||
*/
|
||||
|
||||
public String getRemotePath() {
|
||||
return mRemotePath;
|
||||
}
|
||||
|
||||
public void setRemotePath(String remotePath) {
|
||||
this.mRemotePath = remotePath;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return mMimeType;
|
||||
}
|
||||
|
||||
public void setMimeType(String mimeType) {
|
||||
this.mMimeType = mimeType;
|
||||
}
|
||||
|
||||
public long getLength() {
|
||||
return mLength;
|
||||
}
|
||||
|
||||
public void setLength(long length) {
|
||||
this.mLength = length;
|
||||
}
|
||||
|
||||
public long getCreationTimestamp() {
|
||||
return mCreationTimestamp;
|
||||
}
|
||||
|
||||
public void setCreationTimestamp(long creationTimestamp) {
|
||||
this.mCreationTimestamp = creationTimestamp;
|
||||
}
|
||||
|
||||
public long getModifiedTimestamp() {
|
||||
return mModifiedTimestamp;
|
||||
}
|
||||
|
||||
public void setModifiedTimestamp(long modifiedTimestamp) {
|
||||
this.mModifiedTimestamp = modifiedTimestamp;
|
||||
}
|
||||
|
||||
public String getEtag() {
|
||||
return mEtag;
|
||||
}
|
||||
|
||||
public void setEtag(String etag) {
|
||||
this.mEtag = etag;
|
||||
}
|
||||
|
||||
public String getPermissions() {
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
public void setPermissions(String permissions) {
|
||||
this.mPermissions = permissions;
|
||||
}
|
||||
|
||||
public String getRemoteId() {
|
||||
return mRemoteId;
|
||||
}
|
||||
|
||||
public void setRemoteId(String remoteId) {
|
||||
this.mRemoteId = remoteId;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
public void setSize(long size) {
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
public void setQuotaUsedBytes(BigDecimal quotaUsedBytes) {
|
||||
mQuotaUsedBytes = quotaUsedBytes;
|
||||
}
|
||||
|
||||
public void setQuotaAvailableBytes(BigDecimal quotaAvailableBytes) {
|
||||
mQuotaAvailableBytes = quotaAvailableBytes;
|
||||
}
|
||||
|
||||
public String getPrivateLink() {
|
||||
return mPrivateLink;
|
||||
}
|
||||
|
||||
public void setPrivateLink(String privateLink) {
|
||||
mPrivateLink = privateLink;
|
||||
}
|
||||
|
||||
public RemoteFile() {
|
||||
resetData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link RemoteFile} with given path.
|
||||
*
|
||||
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
|
||||
*
|
||||
* @param path The remote path of the file.
|
||||
*/
|
||||
public RemoteFile(String path) {
|
||||
resetData();
|
||||
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) {
|
||||
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
|
||||
}
|
||||
mRemotePath = path;
|
||||
mCreationTimestamp = 0;
|
||||
mLength = 0;
|
||||
mMimeType = "DIR";
|
||||
mQuotaUsedBytes = BigDecimal.ZERO;
|
||||
mQuotaAvailableBytes = BigDecimal.ZERO;
|
||||
mPrivateLink = null;
|
||||
}
|
||||
|
||||
public RemoteFile(final Response davResource, String userId) {
|
||||
this(getRemotePathFromUrl(davResource.getHref(), userId));
|
||||
final List<Property> properties = davResource.getProperties();
|
||||
|
||||
for(Property property : properties) {
|
||||
if(property instanceof CreationDate)
|
||||
this.setCreationTimestamp(
|
||||
Long.parseLong(((CreationDate) property).getCreationDate()));
|
||||
if(property instanceof GetContentLength)
|
||||
this.setLength(((GetContentLength) property).getContentLength());
|
||||
if(property instanceof GetContentType)
|
||||
this.setMimeType(((GetContentType) property).getType());
|
||||
if(property instanceof GetLastModified)
|
||||
this.setModifiedTimestamp(((GetLastModified) property).getLastModified());
|
||||
if(property instanceof GetETag)
|
||||
this.setEtag(((GetETag) property).getETag());
|
||||
if(property instanceof OCPermissions)
|
||||
this.setPermissions(((OCPermissions) property).getPermission());
|
||||
if(property instanceof OCId)
|
||||
this.setRemoteId(((OCId) property).getId());
|
||||
if(property instanceof OCSize)
|
||||
this.setSize(((OCSize) property).getSize());
|
||||
if(property instanceof QuotaUsedBytes)
|
||||
this.setQuotaUsedBytes(
|
||||
BigDecimal.valueOf(((QuotaUsedBytes) property).getQuotaUsedBytes()));
|
||||
if(property instanceof QuotaAvailableBytes)
|
||||
this.setQuotaAvailableBytes(
|
||||
BigDecimal.valueOf(((QuotaAvailableBytes) property).getQuotaAvailableBytes()));
|
||||
if(property instanceof OCPrivatelink)
|
||||
this.setPrivateLink(((OCPrivatelink) property).getLink());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a relative path from a remote file url
|
||||
*
|
||||
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
|
||||
*
|
||||
* @param url remote file url
|
||||
* @param userId file owner
|
||||
* @return remote relative path of the file
|
||||
*/
|
||||
private static String getRemotePathFromUrl(HttpUrl url, String userId) {
|
||||
final String davFilesPath = WEBDAV_FILES_PATH_4_0 + userId;
|
||||
final String absoluteDavPath = Uri.decode(url.encodedPath());
|
||||
final String pathToOc = absoluteDavPath.split(davFilesPath)[0];
|
||||
return absoluteDavPath.replace(pathToOc + davFilesPath, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used internally. Reset all file properties
|
||||
*/
|
||||
private void resetData() {
|
||||
mRemotePath = null;
|
||||
mMimeType = null;
|
||||
mLength = 0;
|
||||
mCreationTimestamp = 0;
|
||||
mModifiedTimestamp = 0;
|
||||
mEtag = null;
|
||||
mPermissions = null;
|
||||
mRemoteId = null;
|
||||
mSize = 0;
|
||||
mQuotaUsedBytes = null;
|
||||
mQuotaAvailableBytes = null;
|
||||
mPrivateLink = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Methods
|
||||
*/
|
||||
public static final Parcelable.Creator<RemoteFile> CREATOR = new Parcelable.Creator<RemoteFile>() {
|
||||
@Override
|
||||
public RemoteFile createFromParcel(Parcel source) {
|
||||
return new RemoteFile(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteFile[] newArray(int size) {
|
||||
return new RemoteFile[size];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reconstruct from parcel
|
||||
*
|
||||
* @param source The source parcel
|
||||
*/
|
||||
protected RemoteFile(Parcel source) {
|
||||
readFromParcel(source);
|
||||
}
|
||||
|
||||
public void readFromParcel(Parcel source) {
|
||||
mRemotePath = source.readString();
|
||||
mMimeType = source.readString();
|
||||
mLength = source.readLong();
|
||||
mCreationTimestamp = source.readLong();
|
||||
mModifiedTimestamp = source.readLong();
|
||||
mEtag = source.readString();
|
||||
mPermissions = source.readString();
|
||||
mRemoteId = source.readString();
|
||||
mSize = source.readLong();
|
||||
mQuotaUsedBytes = (BigDecimal) source.readSerializable();
|
||||
mQuotaAvailableBytes = (BigDecimal) source.readSerializable();
|
||||
mPrivateLink = source.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return this.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mRemotePath);
|
||||
dest.writeString(mMimeType);
|
||||
dest.writeLong(mLength);
|
||||
dest.writeLong(mCreationTimestamp);
|
||||
dest.writeLong(mModifiedTimestamp);
|
||||
dest.writeString(mEtag);
|
||||
dest.writeString(mPermissions);
|
||||
dest.writeString(mRemoteId);
|
||||
dest.writeLong(mSize);
|
||||
dest.writeSerializable(mQuotaUsedBytes);
|
||||
dest.writeSerializable(mQuotaAvailableBytes);
|
||||
dest.writeString(mPrivateLink);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Remote operation performing the removal of a remote file or folder in the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class RemoveRemoteFileOperation extends RemoteOperation {
|
||||
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
|
||||
private String mRemotePath;
|
||||
|
||||
protected boolean removeChunksFolder = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remotePath RemotePath of the remote file or folder to remove from the server
|
||||
*/
|
||||
public RemoveRemoteFileOperation(String remotePath) {
|
||||
mRemotePath = remotePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the rename operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
||||
try {
|
||||
Uri srcWebDavUri = removeChunksFolder ? client.getUploadsWebDavUri() : client.getUserFilesWebDavUri();
|
||||
|
||||
DeleteMethod deleteMethod = new DeleteMethod(
|
||||
new URL(srcWebDavUri + WebdavUtils.encodePath(mRemotePath)));
|
||||
|
||||
int status = client.executeHttpMethod(deleteMethod);
|
||||
|
||||
result = isSuccess(status) ?
|
||||
new RemoteOperationResult<>(OK) :
|
||||
new RemoteOperationResult<>(deleteMethod);
|
||||
|
||||
Log_OC.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_NO_CONTENT;
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
|
||||
/**
|
||||
* Remote operation performing the rename of a remote file or folder in the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
*/
|
||||
public class RenameRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = RenameRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private static final int RENAME_READ_TIMEOUT = 600000;
|
||||
private static final int RENAME_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private String mOldName;
|
||||
private String mOldRemotePath;
|
||||
private String mNewName;
|
||||
private String mNewRemotePath;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param oldName Old name of the file.
|
||||
* @param oldRemotePath Old remote path of the file.
|
||||
* @param newName New name to set as the name of file.
|
||||
* @param isFolder 'true' for folder and 'false' for files
|
||||
*/
|
||||
public RenameRemoteFileOperation(String oldName, String oldRemotePath, String newName,
|
||||
boolean isFolder) {
|
||||
mOldName = oldName;
|
||||
mOldRemotePath = oldRemotePath;
|
||||
mNewName = newName;
|
||||
|
||||
String parent = (new File(mOldRemotePath)).getParent();
|
||||
parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent +
|
||||
FileUtils.PATH_SEPARATOR;
|
||||
mNewRemotePath = parent + mNewName;
|
||||
if (isFolder) {
|
||||
mNewRemotePath += FileUtils.PATH_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the rename operation.
|
||||
*
|
||||
* @param client Client object to communicate with the remote ownCloud server.
|
||||
*/
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
|
||||
final OwnCloudVersion version = client.getOwnCloudVersion();
|
||||
final boolean versionWithForbiddenChars =
|
||||
(version != null && version.isVersionWithForbiddenCharacters());
|
||||
|
||||
if(!FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars))
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||
|
||||
try {
|
||||
if (mNewName.equals(mOldName)) {
|
||||
return new RemoteOperationResult<>(ResultCode.OK);
|
||||
}
|
||||
|
||||
if (targetPathIsUsed(client)) {
|
||||
return new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||
}
|
||||
|
||||
final MoveMethod move = new MoveMethod(new URL(client.getUserFilesWebDavUri() +
|
||||
WebdavUtils.encodePath(mOldRemotePath)),
|
||||
client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mNewRemotePath), false);
|
||||
|
||||
move.setReadTimeout(RENAME_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
move.setConnectionTimeout(RENAME_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
final int status = client.executeHttpMethod(move);
|
||||
final RemoteOperationResult result =
|
||||
(status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT)
|
||||
? new RemoteOperationResult<>(ResultCode.OK)
|
||||
: new RemoteOperationResult<>(move);
|
||||
|
||||
Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
|
||||
result.getLogMessage()
|
||||
);
|
||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
|
||||
((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ": " +
|
||||
result.getLogMessage(), e);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a file with the new name already exists.
|
||||
*
|
||||
* @return 'True' if the target path is already used by an existing file.
|
||||
*/
|
||||
private boolean targetPathIsUsed(OwnCloudClient client) {
|
||||
ExistenceCheckRemoteOperation existenceCheckRemoteOperation =
|
||||
new ExistenceCheckRemoteOperation(mNewRemotePath, false, false);
|
||||
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
|
||||
return exists.isSuccess();
|
||||
}
|
||||
}
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.PutMethod;
|
||||
import com.owncloud.android.lib.common.network.FileRequestBody;
|
||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Remote operation performing the upload of a remote file to the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
protected String mLocalPath;
|
||||
protected String mRemotePath;
|
||||
protected String mMimeType;
|
||||
protected String mFileLastModifTimestamp;
|
||||
protected PutMethod mPutMethod = null;
|
||||
protected String mRequiredEtag = null;
|
||||
|
||||
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
||||
|
||||
protected FileRequestBody mFileRequestBody = null;
|
||||
|
||||
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType,
|
||||
String fileLastModifTimestamp) {
|
||||
mLocalPath = localPath;
|
||||
mRemotePath = remotePath;
|
||||
mMimeType = mimeType;
|
||||
mFileLastModifTimestamp = fileLastModifTimestamp;
|
||||
}
|
||||
|
||||
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType,
|
||||
String requiredEtag, String fileLastModifTimestamp) {
|
||||
this(localPath, remotePath, mimeType, fileLastModifTimestamp);
|
||||
mRequiredEtag = requiredEtag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
||||
try {
|
||||
mPutMethod = new PutMethod(
|
||||
new URL(client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)));
|
||||
|
||||
mPutMethod.setRetryOnConnectionFailure(false);
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
// the operation was cancelled before getting it's turn to be executed in the queue of uploads
|
||||
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||
} else {
|
||||
// perform the upload
|
||||
result = uploadFile(client);
|
||||
Log_OC.i(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
if (mPutMethod != null && mPutMethod.isAborted()) {
|
||||
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage(), new OperationCancelledException());
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||
result.getLogMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected RemoteOperationResult<? extends Object> uploadFile(OwnCloudClient client) throws Exception {
|
||||
|
||||
File fileToUpload = new File(mLocalPath);
|
||||
|
||||
MediaType mediaType = MediaType.parse(mMimeType);
|
||||
|
||||
mFileRequestBody = new FileRequestBody(fileToUpload, mediaType);
|
||||
|
||||
synchronized (mDataTransferListeners) {
|
||||
mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners);
|
||||
}
|
||||
|
||||
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
||||
mPutMethod.addRequestHeader(HttpConstants.IF_MATCH_HEADER, mRequiredEtag);
|
||||
}
|
||||
|
||||
mPutMethod.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length()));
|
||||
mPutMethod.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
||||
|
||||
mPutMethod.setRequestBody(mFileRequestBody);
|
||||
|
||||
int status = client.executeHttpMethod(mPutMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
return new RemoteOperationResult<>(OK);
|
||||
|
||||
} else { // synchronization failed
|
||||
return new RemoteOperationResult<>(mPutMethod);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
|
||||
return mDataTransferListeners;
|
||||
}
|
||||
|
||||
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.add(listener);
|
||||
}
|
||||
if (mFileRequestBody != null) {
|
||||
mFileRequestBody.addDatatransferProgressListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||
synchronized (mDataTransferListeners) {
|
||||
mDataTransferListeners.remove(listener);
|
||||
}
|
||||
if (mFileRequestBody != null) {
|
||||
mFileRequestBody.removeDatatransferProgressListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
synchronized (mCancellationRequested) {
|
||||
mCancellationRequested.set(true);
|
||||
if (mPutMethod != null)
|
||||
mPutMethod.abort();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSuccess(int status) {
|
||||
return ((status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_CREATED ||
|
||||
status == HttpConstants.HTTP_NO_CONTENT));
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files.chunks;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.methods.webdav.PutMethod;
|
||||
import com.owncloud.android.lib.common.network.ChunkFromFileRequestBody;
|
||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
|
||||
import static com.owncloud.android.lib.common.http.HttpConstants.IF_MATCH_HEADER;
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Remote operation performing the chunked upload of a remote file to the ownCloud server.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation {
|
||||
|
||||
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
||||
public static final long CHUNK_SIZE = 1024000;
|
||||
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
private String mTransferId;
|
||||
|
||||
public ChunkedUploadRemoteFileOperation(String transferId, String localPath, String remotePath, String mimeType,
|
||||
String requiredEtag, String fileLastModifTimestamp) {
|
||||
super(localPath, remotePath, mimeType, requiredEtag, fileLastModifTimestamp);
|
||||
mTransferId = transferId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult uploadFile(OwnCloudClient client) throws Exception {
|
||||
int status;
|
||||
RemoteOperationResult result = null;
|
||||
FileChannel channel;
|
||||
RandomAccessFile raf;
|
||||
|
||||
File fileToUpload = new File(mLocalPath);
|
||||
MediaType mediaType = MediaType.parse(mMimeType);
|
||||
|
||||
raf = new RandomAccessFile(fileToUpload, "r");
|
||||
channel = raf.getChannel();
|
||||
|
||||
mFileRequestBody = new ChunkFromFileRequestBody(fileToUpload, mediaType, channel, CHUNK_SIZE);
|
||||
|
||||
synchronized (mDataTransferListeners) {
|
||||
mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners);
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
String uriPrefix = client.getUploadsWebDavUri() + FileUtils.PATH_SEPARATOR + String.valueOf(mTransferId);
|
||||
long totalLength = fileToUpload.length();
|
||||
long chunkCount = (long) Math.ceil((double) totalLength / 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);
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||
break;
|
||||
} else {
|
||||
if (chunkIndex == chunkCount - 1) {
|
||||
// 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
|
||||
// within that PHP request, so last one takes longer.
|
||||
mPutMethod.setReadTimeout(LAST_CHUNK_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
mPutMethod.setRequestBody(mFileRequestBody);
|
||||
|
||||
status = client.executeHttpMethod(mPutMethod);
|
||||
|
||||
Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath +
|
||||
", chunk index " + chunkIndex + ", count " + chunkCount +
|
||||
", HTTP result status " + status);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
result = new RemoteOperationResult<>(OK);
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(mPutMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channel != null)
|
||||
channel.close();
|
||||
|
||||
if (raf != null)
|
||||
raf.close();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files.chunks;
|
||||
|
||||
import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation;
|
||||
|
||||
/**
|
||||
* Remote operation performing the creation of a new folder to save chunks during an upload to the ownCloud server.
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class CreateRemoteChunkFolderOperation extends CreateRemoteFolderOperation {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remotePath Full path to the new directory to create in the remote server.
|
||||
* @param createFullPath 'True' means that all the ancestor folders should be created.
|
||||
*/
|
||||
public CreateRemoteChunkFolderOperation(String remotePath, boolean createFullPath) {
|
||||
super(remotePath, createFullPath);
|
||||
createChunksFolder = true;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files.chunks;
|
||||
|
||||
import com.owncloud.android.lib.resources.files.MoveRemoteFileOperation;
|
||||
|
||||
/**
|
||||
* Remote operation to move the file built from chunks after uploading it
|
||||
*
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class MoveRemoteChunksFileOperation extends MoveRemoteFileOperation {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param srcRemotePath Remote path of the file/folder to move.
|
||||
* @param targetRemotePath Remove path desired for the file/folder after moving it.
|
||||
* @param overwrite
|
||||
*/
|
||||
public MoveRemoteChunksFileOperation(String srcRemotePath, String targetRemotePath, boolean overwrite,
|
||||
String fileLastModifTimestamp, long fileLength) {
|
||||
super(srcRemotePath, targetRemotePath, overwrite);
|
||||
moveChunkedFile = true;
|
||||
mFileLastModifTimestamp = fileLastModifTimestamp;
|
||||
mFileLength = fileLength;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.files.chunks;
|
||||
|
||||
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
||||
|
||||
public class RemoveRemoteChunksFolderOperation extends RemoveRemoteFileOperation {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remotePath RemotePath of the remote file or folder to remove from the server
|
||||
*/
|
||||
public RemoveRemoteChunksFolderOperation(String remotePath) {
|
||||
super(remotePath);
|
||||
removeChunksFolder = true;
|
||||
}
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import okhttp3.FormBody;
|
||||
|
||||
/**
|
||||
* Creates a new share. This allows sharing with a user or group or as a link.
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class CreateRemoteShareOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = CreateRemoteShareOperation.class.getSimpleName();
|
||||
|
||||
private static final String PARAM_NAME = "name";
|
||||
private static final String PARAM_PASSWORD = "password";
|
||||
private static final String PARAM_EXPIRATION_DATE = "expireDate";
|
||||
private static final String PARAM_PUBLIC_UPLOAD = "publicUpload";
|
||||
private static final String PARAM_PATH = "path";
|
||||
private static final String PARAM_SHARE_TYPE = "shareType";
|
||||
private static final String PARAM_SHARE_WITH = "shareWith";
|
||||
private static final String PARAM_PERMISSIONS = "permissions";
|
||||
private static final String FORMAT_EXPIRATION_DATE = "yyyy-MM-dd";
|
||||
|
||||
private String mRemoteFilePath;
|
||||
private ShareType mShareType;
|
||||
private String mShareWith;
|
||||
private boolean mGetShareDetails;
|
||||
|
||||
/**
|
||||
* Name to set for the public link
|
||||
*/
|
||||
private String mName = "";
|
||||
|
||||
/**
|
||||
* Password to set for the public link
|
||||
*/
|
||||
private String mPassword;
|
||||
|
||||
/**
|
||||
* Expiration date to set for the public link
|
||||
*/
|
||||
private long mExpirationDateInMillis = 0;
|
||||
|
||||
/**
|
||||
* Access permissions for the file bound to the share
|
||||
*/
|
||||
private int mPermissions;
|
||||
|
||||
/**
|
||||
* Upload permissions for the public link (only folders)
|
||||
*/
|
||||
private Boolean mPublicUpload;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remoteFilePath Full path of the file/folder being shared. Mandatory argument
|
||||
* @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument
|
||||
* @param shareWith User/group ID with who the file should be shared. This is mandatory for shareType
|
||||
* of 0 or 1
|
||||
* @param publicUpload If false (default) public cannot upload to a public shared folder.
|
||||
* If true public can upload to a shared folder. Only available for public link shares
|
||||
* @param password Password to protect a public link share. Only available for public link shares
|
||||
* @param permissions 1 - Read only Default for public shares
|
||||
* 2 - Update
|
||||
* 4 - Create
|
||||
* 8 - Delete
|
||||
* 16- Re-share
|
||||
* 31- All above Default for private shares
|
||||
* For user or group shares.
|
||||
* To obtain combinations, add the desired values together.
|
||||
* For instance, for Re-Share, delete, read, update, add 16+8+2+1 = 27.
|
||||
*/
|
||||
public CreateRemoteShareOperation(
|
||||
String remoteFilePath,
|
||||
ShareType shareType,
|
||||
String shareWith,
|
||||
boolean publicUpload,
|
||||
String password,
|
||||
int permissions
|
||||
) {
|
||||
|
||||
mRemoteFilePath = remoteFilePath;
|
||||
mShareType = shareType;
|
||||
mShareWith = shareWith;
|
||||
mPublicUpload = publicUpload;
|
||||
mPassword = password;
|
||||
mPermissions = permissions;
|
||||
mGetShareDetails = false; // defaults to false for backwards compatibility
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set name to create in Share resource. Ignored by servers previous to version 10.0.0
|
||||
*
|
||||
* @param name Name to set to the target share.
|
||||
* Null or empty string result in no value set for the name.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.mName = (name == null) ? "" : name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set password to create in Share resource.
|
||||
*
|
||||
* @param password Password to set to the target share.
|
||||
* Null or empty string result in no value set for the password.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
mPassword = password;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set expiration date to create in Share resource.
|
||||
*
|
||||
* @param expirationDateInMillis Expiration date to set to the target share.
|
||||
* Zero or negative value results in no value sent for expiration date.
|
||||
*/
|
||||
public void setExpirationDate(long expirationDateInMillis) {
|
||||
mExpirationDateInMillis = expirationDateInMillis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set permissions to create in Share resource.
|
||||
*
|
||||
* @param permissions Permissions to set to the target share.
|
||||
* Values <= 0 result in value set to the permissions.
|
||||
*/
|
||||
public void setPermissions(int permissions) {
|
||||
mPermissions = permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* * Enable upload permissions to create in Share resource.
|
||||
* *
|
||||
* * @param publicUpload Upload permission to set to the target share.
|
||||
* * Null results in no update applied to the upload permission.
|
||||
*/
|
||||
public void setPublicUpload(Boolean publicUpload) {
|
||||
mPublicUpload = publicUpload;
|
||||
}
|
||||
|
||||
public void setGetShareDetails(boolean set) {
|
||||
mGetShareDetails = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ShareParserResult> result;
|
||||
|
||||
try {
|
||||
FormBody.Builder formBodyBuilder = new FormBody.Builder()
|
||||
.add(PARAM_PATH, mRemoteFilePath)
|
||||
.add(PARAM_SHARE_TYPE, Integer.toString(mShareType.getValue()))
|
||||
.add(PARAM_SHARE_WITH, mShareWith);
|
||||
|
||||
if (mName.length() > 0) {
|
||||
formBodyBuilder.add(PARAM_NAME, mName);
|
||||
}
|
||||
|
||||
if (mExpirationDateInMillis > 0) {
|
||||
DateFormat dateFormat = new SimpleDateFormat(FORMAT_EXPIRATION_DATE, Locale.getDefault());
|
||||
Calendar expirationDate = Calendar.getInstance();
|
||||
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
||||
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
||||
formBodyBuilder.add(PARAM_EXPIRATION_DATE, formattedExpirationDate);
|
||||
}
|
||||
|
||||
if (mPublicUpload) {
|
||||
formBodyBuilder.add(PARAM_PUBLIC_UPLOAD, Boolean.toString(true));
|
||||
}
|
||||
if (mPassword != null && mPassword.length() > 0) {
|
||||
formBodyBuilder.add(PARAM_PASSWORD, mPassword);
|
||||
}
|
||||
if (OCShare.DEFAULT_PERMISSION != mPermissions) {
|
||||
formBodyBuilder.add(PARAM_PERMISSIONS, Integer.toString(mPermissions));
|
||||
}
|
||||
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
|
||||
PostMethod postMethod = new PostMethod(new URL(uriBuilder.build().toString()));
|
||||
|
||||
postMethod.setRequestBody(formBodyBuilder.build());
|
||||
|
||||
postMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8);
|
||||
postMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(postMethod);
|
||||
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
parser.setOneOrMoreSharesRequired(true);
|
||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||
parser.setServerBaseUri(client.getBaseUri());
|
||||
result = parser.parse(postMethod.getResponseBodyAsString());
|
||||
|
||||
if (result.isSuccess() && mGetShareDetails) {
|
||||
|
||||
// TODO Use executeHttpMethod
|
||||
// retrieve more info - POST only returns the index of the new share
|
||||
OCShare emptyShare = result.getData().getShares().get(0);
|
||||
GetRemoteShareOperation getInfo = new GetRemoteShareOperation(
|
||||
emptyShare.getRemoteId()
|
||||
);
|
||||
result = getInfo.execute(client);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = parser.parse(postMethod.getResponseBodyAsString());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while Creating New Share", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Get the data about a Share resource, known its remote ID.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||
|
||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
||||
|
||||
private long mRemoteId;
|
||||
|
||||
|
||||
public GetRemoteShareOperation(long remoteId) {
|
||||
mRemoteId = remoteId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ShareParserResult> result;
|
||||
|
||||
try {
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
||||
|
||||
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(getMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
// Parse xml response and obtain the list of shares
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
parser.setOneOrMoreSharesRequired(true);
|
||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||
parser.setServerBaseUri(client.getBaseUri());
|
||||
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(getMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Created by masensio on 08/10/2015.
|
||||
*
|
||||
* Retrieves a list of sharees (possible targets of a share) from the ownCloud server.
|
||||
*
|
||||
* Currently only handles users and groups. Users in other OC servers (federation) should be added later.
|
||||
*
|
||||
* Depends on SHAREE API. {@See https://github.com/owncloud/documentation/issues/1626}
|
||||
*
|
||||
* Syntax:
|
||||
* Entry point: ocs/v2.php/apps/files_sharing/api/v1/sharees
|
||||
* HTTP method: GET
|
||||
* url argument: itemType - string, required
|
||||
* url argument: format - string, optional
|
||||
* url argument: search - string, optional
|
||||
* url arguments: perPage - int, optional
|
||||
* url arguments: page - int, optional
|
||||
*
|
||||
* Status codes:
|
||||
* 100 - successful
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObject>> {
|
||||
|
||||
private static final String TAG = GetRemoteShareesOperation.class.getSimpleName();
|
||||
|
||||
// OCS Routes
|
||||
private static final String OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees"; // from OC 8.2
|
||||
|
||||
// Arguments - names
|
||||
private static final String PARAM_FORMAT = "format";
|
||||
private static final String PARAM_ITEM_TYPE = "itemType";
|
||||
private static final String PARAM_SEARCH = "search";
|
||||
private static final String PARAM_PAGE = "page"; // default = 1
|
||||
private static final String PARAM_PER_PAGE = "perPage"; // default = 200
|
||||
|
||||
// Arguments - constant values
|
||||
private static final String VALUE_FORMAT = "json";
|
||||
private static final String VALUE_ITEM_TYPE = "file"; // to get the server search for users / groups
|
||||
|
||||
// JSON Node names
|
||||
private static final String NODE_OCS = "ocs";
|
||||
private static final String NODE_DATA = "data";
|
||||
private static final String NODE_EXACT = "exact";
|
||||
private static final String NODE_USERS = "users";
|
||||
private static final String NODE_GROUPS = "groups";
|
||||
private static final String NODE_REMOTES = "remotes";
|
||||
public static final String NODE_VALUE = "value";
|
||||
public static final String PROPERTY_LABEL = "label";
|
||||
public static final String PROPERTY_SHARE_TYPE = "shareType";
|
||||
public static final String PROPERTY_SHARE_WITH = "shareWith";
|
||||
|
||||
private String mSearchString;
|
||||
private int mPage;
|
||||
private int mPerPage;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param searchString string for searching users, optional
|
||||
* @param page page index in the list of results; beginning in 1
|
||||
* @param perPage maximum number of results in a single page
|
||||
*/
|
||||
public GetRemoteShareesOperation(String searchString, int page, int perPage) {
|
||||
mSearchString = searchString;
|
||||
mPage = page;
|
||||
mPerPage = perPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<ArrayList<JSONObject>> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ArrayList<JSONObject>> result;
|
||||
|
||||
try{
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon()
|
||||
.appendEncodedPath(OCS_ROUTE)
|
||||
.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||
.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE)
|
||||
.appendQueryParameter(PARAM_SEARCH, mSearchString)
|
||||
.appendQueryParameter(PARAM_PAGE, String.valueOf(mPage))
|
||||
.appendQueryParameter(PARAM_PER_PAGE, String.valueOf(mPerPage));
|
||||
|
||||
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(getMethod);
|
||||
String response = getMethod.getResponseBodyAsString();
|
||||
|
||||
if(isSuccess(status)) {
|
||||
Log_OC.d(TAG, "Successful response: " + response);
|
||||
|
||||
// Parse the response
|
||||
JSONObject respJSON = new JSONObject(response);
|
||||
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
|
||||
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
|
||||
JSONObject respExact = respData.getJSONObject(NODE_EXACT);
|
||||
JSONArray respExactUsers = respExact.getJSONArray(NODE_USERS);
|
||||
JSONArray respExactGroups = respExact.getJSONArray(NODE_GROUPS);
|
||||
JSONArray respExactRemotes = respExact.getJSONArray(NODE_REMOTES);
|
||||
JSONArray respPartialUsers = respData.getJSONArray(NODE_USERS);
|
||||
JSONArray respPartialGroups = respData.getJSONArray(NODE_GROUPS);
|
||||
JSONArray respPartialRemotes = respData.getJSONArray(NODE_REMOTES);
|
||||
JSONArray[] jsonResults = {
|
||||
respExactUsers,
|
||||
respExactGroups,
|
||||
respExactRemotes,
|
||||
respPartialUsers,
|
||||
respPartialGroups,
|
||||
respPartialRemotes
|
||||
};
|
||||
|
||||
ArrayList<JSONObject> data = new ArrayList<>(); // For result data
|
||||
for (int i=0; i<6; i++) {
|
||||
for(int j=0; j< jsonResults[i].length(); j++){
|
||||
JSONObject jsonResult = jsonResults[i].getJSONObject(j);
|
||||
data.add(jsonResult);
|
||||
Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL));
|
||||
}
|
||||
}
|
||||
|
||||
result = new RemoteOperationResult<>(OK);
|
||||
result.setData(data);
|
||||
|
||||
Log_OC.d(TAG, "*** Get Users or groups completed " );
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(getMethod);
|
||||
Log_OC.e(TAG, "Failed response while getting users/groups from the server ");
|
||||
if (response != null) {
|
||||
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
||||
} else {
|
||||
Log_OC.e(TAG, "*** status code: " + status);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting users/groups", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Provide a list shares for a specific file.
|
||||
* The input is the full path of the desired file.
|
||||
* The output is a list of everyone who has the file shared with them.
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class GetRemoteSharesForFileOperation extends RemoteOperation<ShareParserResult> {
|
||||
|
||||
private static final String TAG = GetRemoteSharesForFileOperation.class.getSimpleName();
|
||||
|
||||
private static final String PARAM_PATH = "path";
|
||||
private static final String PARAM_RESHARES = "reshares";
|
||||
private static final String PARAM_SUBFILES = "subfiles";
|
||||
|
||||
private String mRemoteFilePath;
|
||||
private boolean mReshares;
|
||||
private boolean mSubfiles;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remoteFilePath Path to file or folder
|
||||
* @param reshares If set to false (default), only shares owned by the current user are
|
||||
* returned.
|
||||
* If set to true, shares owned by any user from the given file are returned.
|
||||
* @param subfiles If set to false (default), lists only the folder being shared
|
||||
* If set to true, all shared files within the folder are returned.
|
||||
*/
|
||||
public GetRemoteSharesForFileOperation(String remoteFilePath, boolean reshares,
|
||||
boolean subfiles) {
|
||||
mRemoteFilePath = remoteFilePath;
|
||||
mReshares = reshares;
|
||||
mSubfiles = subfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ShareParserResult> result;
|
||||
|
||||
try {
|
||||
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
uriBuilder.appendQueryParameter(PARAM_PATH, mRemoteFilePath);
|
||||
uriBuilder.appendQueryParameter(PARAM_RESHARES, String.valueOf(mReshares));
|
||||
uriBuilder.appendQueryParameter(PARAM_SUBFILES, String.valueOf(mSubfiles));
|
||||
|
||||
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(getMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
// Parse xml response and obtain the list of shares
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||
parser.setServerBaseUri(client.getBaseUri());
|
||||
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||
|
||||
if (result.isSuccess()) {
|
||||
Log_OC.d(TAG, "Got " + result.getData().getShares().size() + " shares");
|
||||
}
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(getMethod);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting shares", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Get the data from the server about ALL the known shares owned by the requester.
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class GetRemoteSharesOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = GetRemoteSharesOperation.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
||||
try {
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
|
||||
GetMethod getMethod = new GetMethod(
|
||||
new URL(client.getBaseUri() + ShareUtils.SHARING_API_PATH)
|
||||
);
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(getMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
|
||||
// Parse xml response and obtain the list of shares
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||
parser.setServerBaseUri(client.getBaseUri());
|
||||
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(getMethod);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.shares;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Contains the data of a Share from the Share API
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class OCShare implements Parcelable, Serializable {
|
||||
|
||||
/**
|
||||
* Generated - should be refreshed every time the class changes!!
|
||||
*/
|
||||
private static final long serialVersionUID = 4124975224281327921L;
|
||||
|
||||
private static final String TAG = OCShare.class.getSimpleName();
|
||||
|
||||
public static final int DEFAULT_PERMISSION = -1;
|
||||
public static final int READ_PERMISSION_FLAG = 1;
|
||||
public static final int UPDATE_PERMISSION_FLAG = 2;
|
||||
public static final int CREATE_PERMISSION_FLAG = 4;
|
||||
public static final int DELETE_PERMISSION_FLAG = 8;
|
||||
public static final int SHARE_PERMISSION_FLAG = 16;
|
||||
public static final int MAXIMUM_PERMISSIONS_FOR_FILE =
|
||||
READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG +
|
||||
SHARE_PERMISSION_FLAG;
|
||||
public static final int MAXIMUM_PERMISSIONS_FOR_FOLDER =
|
||||
MAXIMUM_PERMISSIONS_FOR_FILE +
|
||||
CREATE_PERMISSION_FLAG +
|
||||
DELETE_PERMISSION_FLAG;
|
||||
public static final int FEDERATED_PERMISSIONS_FOR_FILE_UP_TO_OC9 =
|
||||
READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG;
|
||||
public static final int FEDERATED_PERMISSIONS_FOR_FILE_AFTER_OC9 =
|
||||
READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG +
|
||||
SHARE_PERMISSION_FLAG;
|
||||
public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 =
|
||||
READ_PERMISSION_FLAG +
|
||||
UPDATE_PERMISSION_FLAG +
|
||||
CREATE_PERMISSION_FLAG +
|
||||
DELETE_PERMISSION_FLAG;
|
||||
public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9 =
|
||||
FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 +
|
||||
SHARE_PERMISSION_FLAG;
|
||||
|
||||
private long mId;
|
||||
private long mFileSource;
|
||||
private long mItemSource;
|
||||
private ShareType mShareType;
|
||||
private String mShareWith;
|
||||
private String mPath;
|
||||
private int mPermissions;
|
||||
private long mSharedDate;
|
||||
private long mExpirationDate;
|
||||
private String mToken;
|
||||
private String mSharedWithDisplayName;
|
||||
private String mName;
|
||||
private boolean mIsFolder;
|
||||
private long mUserId;
|
||||
private long mRemoteId;
|
||||
private String mShareLink;
|
||||
|
||||
public OCShare() {
|
||||
super();
|
||||
resetData();
|
||||
}
|
||||
|
||||
public OCShare(String path) {
|
||||
resetData();
|
||||
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) {
|
||||
Log_OC.e(TAG, "Trying to create a OCShare with a non valid path");
|
||||
throw new IllegalArgumentException("Trying to create a OCShare with a non valid path: " + path);
|
||||
}
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used internally. Reset all file properties
|
||||
*/
|
||||
private void resetData() {
|
||||
mId = -1;
|
||||
mFileSource = 0;
|
||||
mItemSource = 0;
|
||||
mShareType = ShareType.NO_SHARED;
|
||||
mShareWith = "";
|
||||
mPath = "";
|
||||
mPermissions = -1;
|
||||
mSharedDate = 0;
|
||||
mExpirationDate = 0;
|
||||
mToken = "";
|
||||
mSharedWithDisplayName = "";
|
||||
mIsFolder = false;
|
||||
mUserId = -1;
|
||||
mRemoteId = -1;
|
||||
mShareLink = "";
|
||||
mName = "";
|
||||
}
|
||||
|
||||
/// Getters and Setters
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public long getFileSource() {
|
||||
return mFileSource;
|
||||
}
|
||||
|
||||
public void setFileSource(long fileSource) {
|
||||
this.mFileSource = fileSource;
|
||||
}
|
||||
|
||||
public long getItemSource() {
|
||||
return mItemSource;
|
||||
}
|
||||
|
||||
public void setItemSource(long itemSource) {
|
||||
this.mItemSource = itemSource;
|
||||
}
|
||||
|
||||
public ShareType getShareType() {
|
||||
return mShareType;
|
||||
}
|
||||
|
||||
public void setShareType(ShareType shareType) {
|
||||
this.mShareType = shareType;
|
||||
}
|
||||
|
||||
public String getShareWith() {
|
||||
return mShareWith;
|
||||
}
|
||||
|
||||
public void setShareWith(String shareWith) {
|
||||
this.mShareWith = (shareWith != null) ? shareWith : "";
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.mPath = (path != null) ? path : "";
|
||||
}
|
||||
|
||||
public int getPermissions() {
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
public void setPermissions(int permissions) {
|
||||
this.mPermissions = permissions;
|
||||
}
|
||||
|
||||
public long getSharedDate() {
|
||||
return mSharedDate;
|
||||
}
|
||||
|
||||
public void setSharedDate(long sharedDate) {
|
||||
this.mSharedDate = sharedDate;
|
||||
}
|
||||
|
||||
public long getExpirationDate() {
|
||||
return mExpirationDate;
|
||||
}
|
||||
|
||||
public void setExpirationDate(long expirationDate) {
|
||||
this.mExpirationDate = expirationDate;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return mToken;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.mToken = (token != null) ? token : "";
|
||||
}
|
||||
|
||||
public String getSharedWithDisplayName() {
|
||||
return mSharedWithDisplayName;
|
||||
}
|
||||
|
||||
public void setSharedWithDisplayName(String sharedWithDisplayName) {
|
||||
this.mSharedWithDisplayName = (sharedWithDisplayName != null) ? sharedWithDisplayName : "";
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
mName = (name != null) ? name : "";
|
||||
}
|
||||
|
||||
public boolean isFolder() {
|
||||
return mIsFolder;
|
||||
}
|
||||
|
||||
public void setIsFolder(boolean isFolder) {
|
||||
this.mIsFolder = isFolder;
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
public void setUserId(long userId) {
|
||||
this.mUserId = userId;
|
||||
}
|
||||
|
||||
public long getRemoteId() {
|
||||
return mRemoteId;
|
||||
}
|
||||
|
||||
public void setIdRemoteShared(long remoteId) {
|
||||
this.mRemoteId = remoteId;
|
||||
}
|
||||
|
||||
public String getShareLink() {
|
||||
return this.mShareLink;
|
||||
}
|
||||
|
||||
public void setShareLink(String shareLink) {
|
||||
this.mShareLink = (shareLink != null) ? shareLink : "";
|
||||
}
|
||||
|
||||
public boolean isPasswordProtected() {
|
||||
return ShareType.PUBLIC_LINK.equals(mShareType) && mShareWith.length() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Methods
|
||||
*/
|
||||
public static final Parcelable.Creator<OCShare> CREATOR = new Parcelable.Creator<OCShare>() {
|
||||
@Override
|
||||
public OCShare createFromParcel(Parcel source) {
|
||||
return new OCShare(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OCShare[] newArray(int size) {
|
||||
return new OCShare[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reconstruct from parcel
|
||||
*
|
||||
* @param source The source parcel
|
||||
*/
|
||||
protected OCShare(Parcel source) {
|
||||
readFromParcel(source);
|
||||
}
|
||||
|
||||
public void readFromParcel(Parcel source) {
|
||||
mId = source.readLong();
|
||||
|
||||
mFileSource = source.readLong();
|
||||
mItemSource = source.readLong();
|
||||
try {
|
||||
mShareType = ShareType.valueOf(source.readString());
|
||||
} catch (IllegalArgumentException x) {
|
||||
mShareType = ShareType.NO_SHARED;
|
||||
}
|
||||
mShareWith = source.readString();
|
||||
mPath = source.readString();
|
||||
mPermissions = source.readInt();
|
||||
mSharedDate = source.readLong();
|
||||
mExpirationDate = source.readLong();
|
||||
mToken = source.readString();
|
||||
mSharedWithDisplayName = source.readString();
|
||||
mIsFolder = source.readInt() == 0;
|
||||
mUserId = source.readLong();
|
||||
mRemoteId = source.readLong();
|
||||
mShareLink = source.readString();
|
||||
mName = source.readString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return this.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(mId);
|
||||
dest.writeLong(mFileSource);
|
||||
dest.writeLong(mItemSource);
|
||||
dest.writeString((mShareType == null) ? "" : mShareType.name());
|
||||
dest.writeString(mShareWith);
|
||||
dest.writeString(mPath);
|
||||
dest.writeInt(mPermissions);
|
||||
dest.writeLong(mSharedDate);
|
||||
dest.writeLong(mExpirationDate);
|
||||
dest.writeString(mToken);
|
||||
dest.writeString(mSharedWithDisplayName);
|
||||
dest.writeInt(mIsFolder ? 1 : 0);
|
||||
dest.writeLong(mUserId);
|
||||
dest.writeLong(mRemoteId);
|
||||
dest.writeString(mShareLink);
|
||||
dest.writeString(mName);
|
||||
}
|
||||
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Remove a share
|
||||
*
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class RemoveRemoteShareOperation extends RemoteOperation {
|
||||
|
||||
private static final String TAG = RemoveRemoteShareOperation.class.getSimpleName();
|
||||
|
||||
private int mRemoteShareId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param remoteShareId Share ID
|
||||
*/
|
||||
|
||||
public RemoveRemoteShareOperation(int remoteShareId) {
|
||||
mRemoteShareId = remoteShareId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
||||
try {
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
uriBuilder.appendEncodedPath(String.valueOf(mRemoteShareId));
|
||||
|
||||
DeleteMethod deleteMethod = new DeleteMethod(
|
||||
new URL(uriBuilder.build().toString())
|
||||
);
|
||||
|
||||
deleteMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(deleteMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
|
||||
// Parse xml response and obtain the list of shares
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
result = parser.parse(deleteMethod.getResponseBodyAsString());
|
||||
|
||||
Log_OC.d(TAG, "Unshare " + mRemoteShareId + ": " + result.getLogMessage());
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(deleteMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Unshare Link Exception " + result.getLogMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ShareParserResult {
|
||||
private ArrayList<OCShare> shares;
|
||||
private String parserMessage;
|
||||
|
||||
public ShareParserResult(ArrayList<OCShare> shares, String parserMessage) {
|
||||
this.shares = shares;
|
||||
this.parserMessage = parserMessage;
|
||||
}
|
||||
|
||||
public ArrayList<OCShare> getShares() {
|
||||
return shares;
|
||||
}
|
||||
|
||||
public String getParserMessage() {
|
||||
return parserMessage;
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.shares;
|
||||
|
||||
|
||||
/**
|
||||
* Provides method to define a set of share permissions and calculate the appropiate
|
||||
* int value representing it.
|
||||
*/
|
||||
public class SharePermissionsBuilder {
|
||||
|
||||
/** Set of permissions */
|
||||
private int mPermissions = OCShare.READ_PERMISSION_FLAG; // READ is minimum permission
|
||||
|
||||
/**
|
||||
* Sets or clears permission to reshare a file or folder.
|
||||
*
|
||||
* @param enabled 'True' to set, 'false' to clear.
|
||||
* @return Instance to builder itself, to allow consecutive calls to setters
|
||||
*/
|
||||
public SharePermissionsBuilder setSharePermission(boolean enabled) {
|
||||
updatePermission(OCShare.SHARE_PERMISSION_FLAG, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or clears permission to update a folder or folder.
|
||||
*
|
||||
* @param enabled 'True' to set, 'false' to clear.
|
||||
* @return Instance to builder itself, to allow consecutive calls to setters
|
||||
*/
|
||||
public SharePermissionsBuilder setUpdatePermission(boolean enabled) {
|
||||
updatePermission(OCShare.UPDATE_PERMISSION_FLAG, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or clears permission to create files in share folder.
|
||||
*
|
||||
* @param enabled 'True' to set, 'false' to clear.
|
||||
* @return Instance to builder itself, to allow consecutive calls to setters
|
||||
*/
|
||||
public SharePermissionsBuilder setCreatePermission(boolean enabled) {
|
||||
updatePermission(OCShare.CREATE_PERMISSION_FLAG, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or clears permission to delete files in a shared folder.
|
||||
*
|
||||
* @param enabled 'True' to set, 'false' to clear.
|
||||
* @return Instance to builder itself, to allow consecutive calls to setters
|
||||
*/
|
||||
public SharePermissionsBuilder setDeletePermission(boolean enabled) {
|
||||
updatePermission(OCShare.DELETE_PERMISSION_FLAG, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code to update the value of the set of permissions.
|
||||
*
|
||||
* @param permissionsFlag Flag for the permission to update.
|
||||
* @param enable 'True' to set, 'false' to clear.
|
||||
*/
|
||||
private void updatePermission(int permissionsFlag, boolean enable) {
|
||||
if (enable) {
|
||||
// add permission
|
||||
mPermissions |= permissionsFlag;
|
||||
} else {
|
||||
// delete permission
|
||||
mPermissions &= ~permissionsFlag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Builds' the int value for the accumulated set of permissions.
|
||||
*
|
||||
* @return An int value representing the accumulated set of permissions.
|
||||
*/
|
||||
public int build() {
|
||||
return mPermissions;
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ShareToRemoteOperationResultParser {
|
||||
|
||||
private static final String TAG = ShareToRemoteOperationResultParser.class.getSimpleName();
|
||||
|
||||
private ShareXMLParser mShareXmlParser = null;
|
||||
private boolean mOneOrMoreSharesRequired = false;
|
||||
private OwnCloudVersion mOwnCloudVersion = null;
|
||||
private Uri mServerBaseUri = null;
|
||||
|
||||
|
||||
public ShareToRemoteOperationResultParser(ShareXMLParser shareXmlParser) {
|
||||
mShareXmlParser = shareXmlParser;
|
||||
}
|
||||
|
||||
public void setOneOrMoreSharesRequired(boolean oneOrMoreSharesRequired) {
|
||||
mOneOrMoreSharesRequired = oneOrMoreSharesRequired;
|
||||
}
|
||||
|
||||
public void setOwnCloudVersion(OwnCloudVersion ownCloudVersion) {
|
||||
mOwnCloudVersion = ownCloudVersion;
|
||||
}
|
||||
|
||||
public void setServerBaseUri(Uri serverBaseURi) {
|
||||
mServerBaseUri = serverBaseURi;
|
||||
}
|
||||
|
||||
public RemoteOperationResult<ShareParserResult> parse(String serverResponse) {
|
||||
if (serverResponse == null || serverResponse.length() == 0) {
|
||||
return new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||
}
|
||||
|
||||
RemoteOperationResult<ShareParserResult> result;
|
||||
final ArrayList<OCShare> resultData = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// Parse xml response and obtain the list of shares
|
||||
InputStream is = new ByteArrayInputStream(serverResponse.getBytes());
|
||||
if (mShareXmlParser == null) {
|
||||
Log_OC.w(TAG, "No ShareXmlParser provided, creating new instance ");
|
||||
mShareXmlParser = new ShareXMLParser();
|
||||
}
|
||||
List<OCShare> shares = mShareXmlParser.parseXMLResponse(is);
|
||||
|
||||
if (mShareXmlParser.isSuccess()) {
|
||||
if ((shares != null && shares.size() > 0) || !mOneOrMoreSharesRequired) {
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK);
|
||||
if (shares != null) {
|
||||
for (OCShare share : shares) {
|
||||
resultData.add(share);
|
||||
// build the share link if not in the response
|
||||
// (needed for OC servers < 9.0.0, see ShareXMLParser.java#line256)
|
||||
if (share.getShareType() == ShareType.PUBLIC_LINK
|
||||
&& (share.getShareLink() == null
|
||||
|| share.getShareLink().length() <= 0)
|
||||
&& share.getToken().length() > 0) {
|
||||
if (mServerBaseUri != null) {
|
||||
String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion);
|
||||
share.setShareLink(mServerBaseUri + sharingLinkPath + share.getToken());
|
||||
} else {
|
||||
Log_OC.e(TAG, "Couldn't build link for public share :(");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.setData(new ShareParserResult(resultData, ""));
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||
Log_OC.e(TAG, "Successful status with no share in the response");
|
||||
}
|
||||
|
||||
} else if (mShareXmlParser.isWrongParameter()){
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER);
|
||||
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||
|
||||
} else if (mShareXmlParser.isNotFound()){
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND);
|
||||
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||
|
||||
} else if (mShareXmlParser.isForbidden()) {
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_FORBIDDEN);
|
||||
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||
}
|
||||
|
||||
} catch (XmlPullParserException e) {
|
||||
Log_OC.e(TAG, "Error parsing response from server ", e);
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||
|
||||
} catch (IOException e) {
|
||||
Log_OC.e(TAG, "Error reading response from server ", e);
|
||||
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.shares;
|
||||
|
||||
/**
|
||||
* Enum for Share Type, with values:
|
||||
* -1 - No shared
|
||||
* 0 - Shared by user
|
||||
* 1 - Shared by group
|
||||
* 3 - Shared by public link
|
||||
* 4 - Shared by e-mail
|
||||
* 5 - Shared by contact
|
||||
*
|
||||
* @author masensio
|
||||
*
|
||||
*/
|
||||
|
||||
public enum ShareType {
|
||||
NO_SHARED (-1),
|
||||
USER (0),
|
||||
GROUP (1),
|
||||
PUBLIC_LINK (3),
|
||||
EMAIL (4),
|
||||
CONTACT (5),
|
||||
FEDERATED (6);
|
||||
|
||||
private int value;
|
||||
|
||||
private ShareType(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static ShareType fromValue(int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case -1:
|
||||
return NO_SHARED;
|
||||
case 0:
|
||||
return USER;
|
||||
case 1:
|
||||
return GROUP;
|
||||
case 3:
|
||||
return PUBLIC_LINK;
|
||||
case 4:
|
||||
return EMAIL;
|
||||
case 5:
|
||||
return CONTACT;
|
||||
case 6:
|
||||
return FEDERATED;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
|
||||
/**
|
||||
* Contains Constants for Share Operation
|
||||
*
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*
|
||||
*/
|
||||
|
||||
public class ShareUtils {
|
||||
|
||||
// OCS Route
|
||||
public static final String SHARING_API_PATH ="ocs/v2.php/apps/files_sharing/api/v1/shares";
|
||||
|
||||
// String to build the link with the token of a share:
|
||||
public static final String SHARING_LINK_PATH_BEFORE_VERSION_8 = "/public.php?service=files&t=";
|
||||
public static final String SHARING_LINK_PATH_AFTER_VERSION_8 = "/index.php/s/";
|
||||
|
||||
public static String getSharingLinkPath(OwnCloudVersion version){
|
||||
if (version!= null && version.isAfter8Version()){
|
||||
return SHARING_LINK_PATH_AFTER_VERSION_8;
|
||||
} else {
|
||||
return SHARING_LINK_PATH_BEFORE_VERSION_8;
|
||||
}
|
||||
}
|
||||
}
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
//import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||
|
||||
/**
|
||||
* Parser for Share API Response
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class ShareXMLParser {
|
||||
|
||||
//private static final String TAG = ShareXMLParser.class.getSimpleName();
|
||||
|
||||
// No namespaces
|
||||
private static final String ns = null;
|
||||
|
||||
// NODES for XML Parser
|
||||
private static final String NODE_OCS = "ocs";
|
||||
|
||||
private static final String NODE_META = "meta";
|
||||
private static final String NODE_STATUS = "status";
|
||||
private static final String NODE_STATUS_CODE = "statuscode";
|
||||
private static final String NODE_MESSAGE = "message";
|
||||
|
||||
private static final String NODE_DATA = "data";
|
||||
private static final String NODE_ELEMENT = "element";
|
||||
private static final String NODE_ID = "id";
|
||||
private static final String NODE_ITEM_TYPE = "item_type";
|
||||
private static final String NODE_ITEM_SOURCE = "item_source";
|
||||
private static final String NODE_PARENT = "parent";
|
||||
private static final String NODE_SHARE_TYPE = "share_type";
|
||||
private static final String NODE_SHARE_WITH = "share_with";
|
||||
private static final String NODE_FILE_SOURCE = "file_source";
|
||||
private static final String NODE_PATH = "path";
|
||||
private static final String NODE_PERMISSIONS = "permissions";
|
||||
private static final String NODE_STIME = "stime";
|
||||
private static final String NODE_EXPIRATION = "expiration";
|
||||
private static final String NODE_TOKEN = "token";
|
||||
private static final String NODE_STORAGE = "storage";
|
||||
private static final String NODE_MAIL_SEND = "mail_send";
|
||||
private static final String NODE_SHARE_WITH_DISPLAY_NAME = "share_with_displayname";
|
||||
private static final String NODE_NAME = "name";
|
||||
|
||||
private static final String NODE_URL = "url";
|
||||
|
||||
private static final String TYPE_FOLDER = "folder";
|
||||
|
||||
private static final int SUCCESS = 200;
|
||||
private static final int ERROR_WRONG_PARAMETER = 400;
|
||||
private static final int ERROR_FORBIDDEN = 403;
|
||||
private static final int ERROR_NOT_FOUND = 404;
|
||||
|
||||
private String mStatus;
|
||||
private int mStatusCode;
|
||||
private String mMessage;
|
||||
|
||||
// Getters and Setters
|
||||
public String getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.mStatus = status;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return mStatusCode;
|
||||
}
|
||||
|
||||
public void setStatusCode(int statusCode) {
|
||||
this.mStatusCode = statusCode;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.mMessage = message;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
public ShareXMLParser() {
|
||||
mStatusCode = -1;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return mStatusCode == SUCCESS;
|
||||
}
|
||||
|
||||
public boolean isForbidden() {
|
||||
return mStatusCode == ERROR_FORBIDDEN;
|
||||
}
|
||||
|
||||
public boolean isNotFound() {
|
||||
return mStatusCode == ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
public boolean isWrongParameter() {
|
||||
return mStatusCode == ERROR_WRONG_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse is as response of Share API
|
||||
* @param is
|
||||
* @return List of ShareRemoteFiles
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ArrayList<OCShare> parseXMLResponse(InputStream is) throws XmlPullParserException,
|
||||
IOException {
|
||||
|
||||
try {
|
||||
// XMLPullParser
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||
parser.setInput(is, null);
|
||||
parser.nextTag();
|
||||
return readOCS(parser);
|
||||
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse OCS node
|
||||
* @param parser
|
||||
* @return List of ShareRemoteFiles
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private ArrayList<OCShare> readOCS (XmlPullParser parser) throws XmlPullParserException,
|
||||
IOException {
|
||||
ArrayList<OCShare> shares = new ArrayList<>();
|
||||
parser.require(XmlPullParser.START_TAG, ns , NODE_OCS);
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getName();
|
||||
// read NODE_META and NODE_DATA
|
||||
if (name.equalsIgnoreCase(NODE_META)) {
|
||||
readMeta(parser);
|
||||
} else if (name.equalsIgnoreCase(NODE_DATA)) {
|
||||
shares = readData(parser);
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
|
||||
}
|
||||
return shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Meta node
|
||||
* @param parser
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void readMeta(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
parser.require(XmlPullParser.START_TAG, ns, NODE_META);
|
||||
//Log_OC.d(TAG, "---- NODE META ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getName();
|
||||
|
||||
if (name.equalsIgnoreCase(NODE_STATUS)) {
|
||||
setStatus(readNode(parser, NODE_STATUS));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_STATUS_CODE)) {
|
||||
setStatusCode(Integer.parseInt(readNode(parser, NODE_STATUS_CODE)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_MESSAGE)) {
|
||||
setMessage(readNode(parser, NODE_MESSAGE));
|
||||
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Data node
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private ArrayList<OCShare> readData(XmlPullParser parser) throws XmlPullParserException,
|
||||
IOException {
|
||||
ArrayList<OCShare> shares = new ArrayList<OCShare>();
|
||||
OCShare share = null;
|
||||
|
||||
parser.require(XmlPullParser.START_TAG, ns, NODE_DATA);
|
||||
//Log_OC.d(TAG, "---- NODE DATA ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getName();
|
||||
if (name.equalsIgnoreCase(NODE_ELEMENT)) {
|
||||
readElement(parser, shares);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_ID)) {// Parse Create XML Response
|
||||
share = new OCShare();
|
||||
String value = readNode(parser, NODE_ID);
|
||||
share.setIdRemoteShared(Integer.parseInt(value));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_URL)) {
|
||||
// NOTE: this field is received in all the public shares from OC 9.0.0
|
||||
// in previous versions, it's received in the result of POST requests, but not
|
||||
// in GET requests
|
||||
share.setShareType(ShareType.PUBLIC_LINK);
|
||||
String value = readNode(parser, NODE_URL);
|
||||
share.setShareLink(value);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_TOKEN)) {
|
||||
share.setToken(readNode(parser, NODE_TOKEN));
|
||||
|
||||
} else {
|
||||
skip(parser);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (share != null) {
|
||||
// this is the response of a request for creation; don't pass to isValidShare()
|
||||
shares.add(share);
|
||||
}
|
||||
|
||||
return shares;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse Element node
|
||||
* @param parser
|
||||
* @return
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void readElement(XmlPullParser parser, ArrayList<OCShare> shares)
|
||||
throws XmlPullParserException, IOException {
|
||||
parser.require(XmlPullParser.START_TAG, ns, NODE_ELEMENT);
|
||||
|
||||
OCShare share = new OCShare();
|
||||
|
||||
//Log_OC.d(TAG, "---- NODE ELEMENT ---");
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = parser.getName();
|
||||
|
||||
if (name.equalsIgnoreCase(NODE_ELEMENT)) {
|
||||
// patch to work around servers responding with extra <element> surrounding all
|
||||
// the shares on the same file before
|
||||
// https://github.com/owncloud/core/issues/6992 was fixed
|
||||
readElement(parser, shares);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_ID)) {
|
||||
share.setIdRemoteShared(Integer.parseInt(readNode(parser, NODE_ID)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_ITEM_TYPE)) {
|
||||
share.setIsFolder(readNode(parser, NODE_ITEM_TYPE).equalsIgnoreCase(TYPE_FOLDER));
|
||||
fixPathForFolder(share);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_ITEM_SOURCE)) {
|
||||
share.setItemSource(Long.parseLong(readNode(parser, NODE_ITEM_SOURCE)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_PARENT)) {
|
||||
readNode(parser, NODE_PARENT);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_SHARE_TYPE)) {
|
||||
int value = Integer.parseInt(readNode(parser, NODE_SHARE_TYPE));
|
||||
share.setShareType(ShareType.fromValue(value));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_SHARE_WITH)) {
|
||||
share.setShareWith(readNode(parser, NODE_SHARE_WITH));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_FILE_SOURCE)) {
|
||||
share.setFileSource(Long.parseLong(readNode(parser, NODE_FILE_SOURCE)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_PATH)) {
|
||||
share.setPath(readNode(parser, NODE_PATH));
|
||||
fixPathForFolder(share);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_PERMISSIONS)) {
|
||||
share.setPermissions(Integer.parseInt(readNode(parser, NODE_PERMISSIONS)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_STIME)) {
|
||||
share.setSharedDate(Long.parseLong(readNode(parser, NODE_STIME)));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_EXPIRATION)) {
|
||||
String value = readNode(parser, NODE_EXPIRATION);
|
||||
if (!(value.length() == 0)) {
|
||||
share.setExpirationDate(WebdavUtils.parseResponseDate(value).getTime());
|
||||
}
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_TOKEN)) {
|
||||
share.setToken(readNode(parser, NODE_TOKEN));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_STORAGE)) {
|
||||
readNode(parser, NODE_STORAGE);
|
||||
} else if (name.equalsIgnoreCase(NODE_MAIL_SEND)) {
|
||||
readNode(parser, NODE_MAIL_SEND);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_SHARE_WITH_DISPLAY_NAME)) {
|
||||
share.setSharedWithDisplayName(readNode(parser, NODE_SHARE_WITH_DISPLAY_NAME));
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_URL)) {
|
||||
String value = readNode(parser, NODE_URL);
|
||||
share.setShareLink(value);
|
||||
|
||||
} else if (name.equalsIgnoreCase(NODE_NAME)) {
|
||||
share.setName(readNode(parser, NODE_NAME));
|
||||
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
}
|
||||
|
||||
if (isValidShare(share)) {
|
||||
shares.add(share);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidShare(OCShare share) {
|
||||
return (share.getRemoteId() > -1);
|
||||
}
|
||||
|
||||
private void fixPathForFolder(OCShare share) {
|
||||
if (share.isFolder() && share.getPath() != null && share.getPath().length() > 0 &&
|
||||
!share.getPath().endsWith(FileUtils.PATH_SEPARATOR)) {
|
||||
share.setPath(share.getPath() + FileUtils.PATH_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a node, to obtain its text. Needs readText method
|
||||
* @param parser
|
||||
* @param node
|
||||
* @return Text of the node
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private String readNode (XmlPullParser parser, String node) throws XmlPullParserException,
|
||||
IOException{
|
||||
parser.require(XmlPullParser.START_TAG, ns, node);
|
||||
String value = readText(parser);
|
||||
//Log_OC.d(TAG, "node= " + node + ", value= " + value);
|
||||
parser.require(XmlPullParser.END_TAG, ns, node);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the text from a node
|
||||
* @param parser
|
||||
* @return Text of the node
|
||||
* @throws IOException
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||
String result = "";
|
||||
if (parser.next() == XmlPullParser.TEXT) {
|
||||
result = parser.getText();
|
||||
parser.nextTag();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip tags in parser procedure
|
||||
* @param parser
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int depth = 1;
|
||||
while (depth != 0) {
|
||||
switch (parser.next()) {
|
||||
case XmlPullParser.END_TAG:
|
||||
depth--;
|
||||
break;
|
||||
case XmlPullParser.START_TAG:
|
||||
depth++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* Copyright (C) 2018 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.shares;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PutMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import okhttp3.FormBody;
|
||||
|
||||
/**
|
||||
* Updates parameters of an existing Share resource, known its remote ID.
|
||||
*
|
||||
* Allow updating several parameters, triggering a request to the server per parameter.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||
|
||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
||||
|
||||
private static final String PARAM_NAME = "name";
|
||||
private static final String PARAM_PASSWORD = "password";
|
||||
private static final String PARAM_EXPIRATION_DATE = "expireDate";
|
||||
private static final String PARAM_PERMISSIONS = "permissions";
|
||||
private static final String PARAM_PUBLIC_UPLOAD = "publicUpload";
|
||||
private static final String FORMAT_EXPIRATION_DATE = "yyyy-MM-dd";
|
||||
private static final String ENTITY_CONTENT_TYPE = "application/x-www-form-urlencoded";
|
||||
private static final String ENTITY_CHARSET = "UTF-8";
|
||||
|
||||
|
||||
/**
|
||||
* Identifier of the share to update
|
||||
*/
|
||||
private long mRemoteId;
|
||||
|
||||
/**
|
||||
* Password to set for the public link
|
||||
*/
|
||||
private String mPassword;
|
||||
|
||||
/**
|
||||
* Expiration date to set for the public link
|
||||
*/
|
||||
private long mExpirationDateInMillis;
|
||||
|
||||
/**
|
||||
* Access permissions for the file bound to the share
|
||||
*/
|
||||
private int mPermissions;
|
||||
|
||||
/**
|
||||
* Upload permissions for the public link (only folders)
|
||||
*/
|
||||
private Boolean mPublicUpload;
|
||||
private String mName;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor. No update is initialized by default, need to be applied with setters below.
|
||||
*
|
||||
* @param remoteId Identifier of the share to update.
|
||||
*/
|
||||
public UpdateRemoteShareOperation(long remoteId) {
|
||||
mRemoteId = remoteId;
|
||||
mPassword = null; // no update
|
||||
mExpirationDateInMillis = 0; // no update
|
||||
mPublicUpload = null;
|
||||
mPermissions = OCShare.DEFAULT_PERMISSION;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set name to update in Share resource. Ignored by servers previous to version 10.0.0
|
||||
*
|
||||
* @param name Name to set to the target share.
|
||||
* Empty string clears the current name.
|
||||
* Null results in no update applied to the name.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.mName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set password to update in Share resource.
|
||||
*
|
||||
* @param password Password to set to the target share.
|
||||
* Empty string clears the current password.
|
||||
* Null results in no update applied to the password.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
mPassword = password;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set expiration date to update in Share resource.
|
||||
*
|
||||
* @param expirationDateInMillis Expiration date to set to the target share.
|
||||
* A negative value clears the current expiration date.
|
||||
* Zero value (start-of-epoch) results in no update done on
|
||||
* the expiration date.
|
||||
*/
|
||||
public void setExpirationDate(long expirationDateInMillis) {
|
||||
mExpirationDateInMillis = expirationDateInMillis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set permissions to update in Share resource.
|
||||
*
|
||||
* @param permissions Permissions to set to the target share.
|
||||
* Values <= 0 result in no update applied to the permissions.
|
||||
*/
|
||||
public void setPermissions(int permissions) {
|
||||
mPermissions = permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable upload permissions to update in Share resource.
|
||||
*
|
||||
* @param publicUpload Upload permission to set to the target share.
|
||||
* Null results in no update applied to the upload permission.
|
||||
*/
|
||||
public void setPublicUpload(Boolean publicUpload) {
|
||||
mPublicUpload = publicUpload;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<ShareParserResult> result;
|
||||
|
||||
try {
|
||||
FormBody.Builder formBodyBuilder = new FormBody.Builder();
|
||||
|
||||
// Parameters to update
|
||||
if (mName != null) {
|
||||
formBodyBuilder.add(PARAM_NAME, mName);
|
||||
}
|
||||
|
||||
if (mExpirationDateInMillis < 0) {
|
||||
// clear expiration date
|
||||
formBodyBuilder.add(PARAM_EXPIRATION_DATE, "");
|
||||
|
||||
} else if (mExpirationDateInMillis > 0) {
|
||||
// set expiration date
|
||||
DateFormat dateFormat = new SimpleDateFormat(FORMAT_EXPIRATION_DATE, Locale.GERMAN);
|
||||
Calendar expirationDate = Calendar.getInstance();
|
||||
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
||||
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
||||
formBodyBuilder.add(PARAM_EXPIRATION_DATE, formattedExpirationDate);
|
||||
} // else, ignore - no update
|
||||
|
||||
if (mPublicUpload != null) {
|
||||
formBodyBuilder.add(PARAM_PUBLIC_UPLOAD, Boolean.toString(mPublicUpload));
|
||||
}
|
||||
|
||||
// IMPORTANT: permissions parameter needs to be updated after mPublicUpload parameter,
|
||||
// otherwise they would be set always as 1 (READ) in the server when mPublicUpload was updated
|
||||
if (mPermissions > 0) {
|
||||
// set permissions
|
||||
formBodyBuilder.add(PARAM_PERMISSIONS, Integer.toString(mPermissions));
|
||||
}
|
||||
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
||||
|
||||
PutMethod putMethod = new PutMethod(new URL(uriBuilder.build().toString()));
|
||||
|
||||
putMethod.setRequestBody(formBodyBuilder.build());
|
||||
|
||||
putMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8);
|
||||
putMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(putMethod);
|
||||
|
||||
if (isSuccess(status)) {
|
||||
// Parse xml response
|
||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||
new ShareXMLParser()
|
||||
);
|
||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||
parser.setServerBaseUri(client.getBaseUri());
|
||||
result = parser.parse(putMethod.getResponseBodyAsString());
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(putMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while Creating New Share", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* @author masensio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.status;
|
||||
|
||||
/**
|
||||
* Enum for Boolean Type in OCCapability parameters, with values:
|
||||
* -1 - Unknown
|
||||
* 0 - False
|
||||
* 1 - True
|
||||
*/
|
||||
public enum CapabilityBooleanType {
|
||||
UNKNOWN (-1),
|
||||
FALSE (0),
|
||||
TRUE (1);
|
||||
|
||||
private int value;
|
||||
|
||||
CapabilityBooleanType(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static CapabilityBooleanType fromValue(int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case -1:
|
||||
return UNKNOWN;
|
||||
case 0:
|
||||
return FALSE;
|
||||
case 1:
|
||||
return TRUE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CapabilityBooleanType fromBooleanValue(boolean boolValue){
|
||||
if (boolValue){
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUnknown(){
|
||||
return getValue() == -1;
|
||||
}
|
||||
|
||||
public boolean isFalse(){
|
||||
return getValue() == 0;
|
||||
}
|
||||
|
||||
public boolean isTrue(){
|
||||
return getValue() == 1;
|
||||
}
|
||||
|
||||
};
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author masensio
|
||||
* @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package com.owncloud.android.lib.resources.status;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Get the Capabilities from the server
|
||||
* Save in Result.getData in a OCCapability object
|
||||
*
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability> {
|
||||
|
||||
private static final String TAG = GetRemoteCapabilitiesOperation.class.getSimpleName();
|
||||
|
||||
// OCS Routes
|
||||
private static final String OCS_ROUTE = "ocs/v2.php/cloud/capabilities";
|
||||
|
||||
// Arguments - names
|
||||
private static final String PARAM_FORMAT = "format";
|
||||
|
||||
// Arguments - constant values
|
||||
private static final String VALUE_FORMAT = "json";
|
||||
|
||||
// JSON Node names
|
||||
private static final String NODE_OCS = "ocs";
|
||||
|
||||
private static final String NODE_META = "meta";
|
||||
|
||||
private static final String NODE_DATA = "data";
|
||||
private static final String NODE_VERSION = "version";
|
||||
|
||||
private static final String NODE_CAPABILITIES = "capabilities";
|
||||
private static final String NODE_CORE = "core";
|
||||
|
||||
private static final String NODE_FILES_SHARING = "files_sharing";
|
||||
private static final String NODE_PUBLIC = "public";
|
||||
private static final String NODE_PASSWORD = "password";
|
||||
private static final String NODE_EXPIRE_DATE = "expire_date";
|
||||
private static final String NODE_USER = "user";
|
||||
private static final String NODE_FEDERATION = "federation";
|
||||
private static final String NODE_FILES = "files";
|
||||
|
||||
private static final String PROPERTY_STATUS = "status";
|
||||
private static final String PROPERTY_STATUSCODE = "statuscode";
|
||||
private static final String PROPERTY_MESSAGE = "message";
|
||||
|
||||
private static final String PROPERTY_POLLINTERVAL = "pollinterval";
|
||||
|
||||
private static final String PROPERTY_MAJOR = "major";
|
||||
private static final String PROPERTY_MINOR = "minor";
|
||||
private static final String PROPERTY_MICRO = "micro";
|
||||
private static final String PROPERTY_STRING = "string";
|
||||
private static final String PROPERTY_EDITION = "edition";
|
||||
|
||||
private static final String PROPERTY_API_ENABLED = "api_enabled";
|
||||
private static final String PROPERTY_ENABLED = "enabled";
|
||||
private static final String PROPERTY_ENFORCED = "enforced";
|
||||
private static final String PROPERTY_DAYS = "days";
|
||||
private static final String PROPERTY_SEND_MAIL = "send_mail";
|
||||
private static final String PROPERTY_UPLOAD = "upload";
|
||||
private static final String PROPERTY_UPLOAD_ONLY = "supports_upload_only";
|
||||
private static final String PROPERTY_MULTIPLE = "multiple";
|
||||
private static final String PROPERTY_RESHARING = "resharing";
|
||||
private static final String PROPERTY_OUTGOING = "outgoing";
|
||||
private static final String PROPERTY_INCOMING = "incoming";
|
||||
|
||||
private static final String PROPERTY_BIGFILECHUNKING = "bigfilechunking";
|
||||
private static final String PROPERTY_UNDELETE = "undelete";
|
||||
private static final String PROPERTY_VERSIONING = "versioning";
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public GetRemoteCapabilitiesOperation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<OCCapability> run(OwnCloudClient client) {
|
||||
RemoteOperationResult<OCCapability> result;
|
||||
|
||||
try {
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(OCS_ROUTE); // avoid starting "/" in this method
|
||||
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT);
|
||||
|
||||
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
||||
int status = client.executeHttpMethod(getMethod);
|
||||
|
||||
String response = getMethod.getResponseBodyAsString();
|
||||
if(isSuccess(status)) {
|
||||
Log_OC.d(TAG, "Successful response: " + response);
|
||||
|
||||
// Parse the response
|
||||
JSONObject respJSON = new JSONObject(response);
|
||||
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
|
||||
JSONObject respMeta = respOCS.getJSONObject(NODE_META);
|
||||
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
|
||||
|
||||
// Read meta
|
||||
boolean statusProp = respMeta.getString(PROPERTY_STATUS).equalsIgnoreCase("ok");
|
||||
int statuscode = respMeta.getInt(PROPERTY_STATUSCODE);
|
||||
String message = respMeta.getString(PROPERTY_MESSAGE);
|
||||
|
||||
if (statusProp) {
|
||||
OCCapability capability = new OCCapability();
|
||||
// Add Version
|
||||
if (respData.has(NODE_VERSION)) {
|
||||
JSONObject respVersion = respData.getJSONObject(NODE_VERSION);
|
||||
capability.setVersionMayor(respVersion.getInt(PROPERTY_MAJOR));
|
||||
capability.setVersionMinor(respVersion.getInt(PROPERTY_MINOR));
|
||||
capability.setVersionMicro(respVersion.getInt(PROPERTY_MICRO));
|
||||
capability.setVersionString(respVersion.getString(PROPERTY_STRING));
|
||||
capability.setVersionEdition(respVersion.getString(PROPERTY_EDITION));
|
||||
Log_OC.d(TAG, "*** Added " + NODE_VERSION);
|
||||
}
|
||||
|
||||
// Capabilities Object
|
||||
if (respData.has(NODE_CAPABILITIES)) {
|
||||
JSONObject respCapabilities = respData.getJSONObject(NODE_CAPABILITIES);
|
||||
|
||||
// Add Core: pollinterval
|
||||
if (respCapabilities.has(NODE_CORE)) {
|
||||
JSONObject respCore = respCapabilities.getJSONObject(NODE_CORE);
|
||||
capability.setCorePollinterval(respCore.getInt(PROPERTY_POLLINTERVAL));
|
||||
Log_OC.d(TAG, "*** Added " + NODE_CORE);
|
||||
}
|
||||
|
||||
// Add files_sharing: public, user, resharing
|
||||
if (respCapabilities.has(NODE_FILES_SHARING)) {
|
||||
JSONObject respFilesSharing = respCapabilities.getJSONObject(NODE_FILES_SHARING);
|
||||
if (respFilesSharing.has(PROPERTY_API_ENABLED)) {
|
||||
capability.setFilesSharingApiEnabled(CapabilityBooleanType.fromBooleanValue(
|
||||
respFilesSharing.getBoolean(PROPERTY_API_ENABLED)));
|
||||
}
|
||||
|
||||
if (respFilesSharing.has(NODE_PUBLIC)) {
|
||||
JSONObject respPublic = respFilesSharing.getJSONObject(NODE_PUBLIC);
|
||||
capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_ENABLED)));
|
||||
if(respPublic.has(NODE_PASSWORD)) {
|
||||
capability.setFilesSharingPublicPasswordEnforced(
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getJSONObject(NODE_PASSWORD).getBoolean(PROPERTY_ENFORCED)));
|
||||
}
|
||||
if(respPublic.has(NODE_EXPIRE_DATE)){
|
||||
JSONObject respExpireDate = respPublic.getJSONObject(NODE_EXPIRE_DATE);
|
||||
capability.setFilesSharingPublicExpireDateEnabled(
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respExpireDate.getBoolean(PROPERTY_ENABLED)));
|
||||
if (respExpireDate.has(PROPERTY_DAYS)) {
|
||||
capability.setFilesSharingPublicExpireDateDays(
|
||||
respExpireDate.getInt(PROPERTY_DAYS));
|
||||
}
|
||||
if (respExpireDate.has(PROPERTY_ENFORCED)) {
|
||||
capability.setFilesSharingPublicExpireDateEnforced(
|
||||
CapabilityBooleanType.fromBooleanValue(
|
||||
respExpireDate.getBoolean(PROPERTY_ENFORCED)));
|
||||
}
|
||||
}
|
||||
if (respPublic.has(PROPERTY_UPLOAD)){
|
||||
capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_UPLOAD)));
|
||||
}
|
||||
if (respPublic.has(PROPERTY_UPLOAD_ONLY)) {
|
||||
capability.setFilesSharingPublicSupportsUploadOnly(CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_UPLOAD_ONLY)));
|
||||
}
|
||||
if (respPublic.has(PROPERTY_MULTIPLE)) {
|
||||
capability.setFilesSharingPublicMultiple(CapabilityBooleanType.fromBooleanValue(
|
||||
respPublic.getBoolean(PROPERTY_MULTIPLE)));
|
||||
}
|
||||
}
|
||||
|
||||
if (respFilesSharing.has(NODE_USER)) {
|
||||
JSONObject respUser = respFilesSharing.getJSONObject(NODE_USER);
|
||||
capability.setFilesSharingUserSendMail(CapabilityBooleanType.fromBooleanValue(
|
||||
respUser.getBoolean(PROPERTY_SEND_MAIL)));
|
||||
}
|
||||
|
||||
capability.setFilesSharingResharing(CapabilityBooleanType.fromBooleanValue(
|
||||
respFilesSharing.getBoolean(PROPERTY_RESHARING)));
|
||||
if (respFilesSharing.has(NODE_FEDERATION)) {
|
||||
JSONObject respFederation = respFilesSharing.getJSONObject(NODE_FEDERATION);
|
||||
capability.setFilesSharingFederationOutgoing(
|
||||
CapabilityBooleanType.fromBooleanValue(respFederation.getBoolean(PROPERTY_OUTGOING)));
|
||||
capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromBooleanValue(
|
||||
respFederation.getBoolean(PROPERTY_INCOMING)));
|
||||
}
|
||||
Log_OC.d(TAG, "*** Added " + NODE_FILES_SHARING);
|
||||
}
|
||||
|
||||
|
||||
if (respCapabilities.has(NODE_FILES)) {
|
||||
JSONObject respFiles = respCapabilities.getJSONObject(NODE_FILES);
|
||||
// Add files
|
||||
capability.setFilesBigFileChuncking(CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_BIGFILECHUNKING)));
|
||||
if (respFiles.has(PROPERTY_UNDELETE)) {
|
||||
capability.setFilesUndelete(CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_UNDELETE)));
|
||||
}
|
||||
if (respFiles.has(PROPERTY_VERSIONING)) {
|
||||
capability.setFilesVersioning(CapabilityBooleanType.fromBooleanValue(
|
||||
respFiles.getBoolean(PROPERTY_VERSIONING)));
|
||||
}
|
||||
Log_OC.d(TAG, "*** Added " + NODE_FILES);
|
||||
}
|
||||
}
|
||||
// Result
|
||||
result = new RemoteOperationResult<>(OK);
|
||||
result.setData(capability);
|
||||
|
||||
Log_OC.d(TAG, "*** Get Capabilities completed ");
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(statuscode, message, null);
|
||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
||||
Log_OC.e(TAG, "*** status: " + statusProp + "; message: " + message);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(getMethod);
|
||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
||||
if (response != null) {
|
||||
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
||||
} else {
|
||||
Log_OC.e(TAG, "*** status code: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
Log_OC.e(TAG, "Exception while getting capabilities", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2018 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.status;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||
|
||||
/**
|
||||
* Checks if the server is valid and if the server supports the Share API
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author masensio
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
|
||||
public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
|
||||
|
||||
/**
|
||||
* Maximum time to wait for a response from the server when the connection is being tested,
|
||||
* in MILLISECONDs.
|
||||
*/
|
||||
public static final long TRY_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
private static final String TAG = GetRemoteStatusOperation.class.getSimpleName();
|
||||
|
||||
private static final String NODE_INSTALLED = "installed";
|
||||
private static final String NODE_VERSION = "version";
|
||||
private static final String HTTPS_PREFIX = "https://";
|
||||
private static final String HTTP_PREFIX = "http://";
|
||||
|
||||
private RemoteOperationResult<OwnCloudVersion> mLatestResult;
|
||||
private Context mContext;
|
||||
|
||||
public GetRemoteStatusOperation(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
private boolean tryConnection(OwnCloudClient client) {
|
||||
boolean retval = false;
|
||||
String baseUrlSt = client.getBaseUri().toString();
|
||||
try {
|
||||
GetMethod getMethod = new GetMethod(new URL(baseUrlSt + OwnCloudClient.STATUS_PATH));
|
||||
|
||||
getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
client.setFollowRedirects(false);
|
||||
boolean isRedirectToNonSecureConnection = false;
|
||||
int status;
|
||||
try {
|
||||
status = client.executeHttpMethod(getMethod);
|
||||
mLatestResult = isSuccess(status)
|
||||
? new RemoteOperationResult<>(OK)
|
||||
: new RemoteOperationResult<>(getMethod);
|
||||
} catch (SSLException sslE) {
|
||||
mLatestResult = new RemoteOperationResult(sslE);
|
||||
return false;
|
||||
}
|
||||
|
||||
String redirectedLocation = mLatestResult.getRedirectedLocation();
|
||||
while (redirectedLocation != null && redirectedLocation.length() > 0
|
||||
&& !mLatestResult.isSuccess()) {
|
||||
|
||||
isRedirectToNonSecureConnection |= (
|
||||
baseUrlSt.startsWith(HTTPS_PREFIX) &&
|
||||
redirectedLocation.startsWith(HTTP_PREFIX)
|
||||
);
|
||||
|
||||
getMethod = new GetMethod(new URL(redirectedLocation));
|
||||
getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
status = client.executeHttpMethod(getMethod);
|
||||
mLatestResult = new RemoteOperationResult<>(getMethod);
|
||||
redirectedLocation = mLatestResult.getRedirectedLocation();
|
||||
}
|
||||
|
||||
if (isSuccess(status)) {
|
||||
|
||||
JSONObject respJSON = new JSONObject(getMethod.getResponseBodyAsString());
|
||||
if (!respJSON.getBoolean(NODE_INSTALLED)) {
|
||||
mLatestResult = new RemoteOperationResult(
|
||||
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
||||
} else {
|
||||
String version = respJSON.getString(NODE_VERSION);
|
||||
OwnCloudVersion ocVersion = new OwnCloudVersion(version);
|
||||
/// the version object will be returned even if the version is invalid, no error code;
|
||||
/// every app will decide how to act if (ocVersion.isVersionValid() == false)
|
||||
|
||||
if (isRedirectToNonSecureConnection) {
|
||||
mLatestResult = new RemoteOperationResult<>(
|
||||
RemoteOperationResult.ResultCode.
|
||||
OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
||||
} else {
|
||||
mLatestResult = new RemoteOperationResult<>(
|
||||
baseUrlSt.startsWith(HTTPS_PREFIX) ?
|
||||
RemoteOperationResult.ResultCode.OK_SSL :
|
||||
RemoteOperationResult.ResultCode.OK_NO_SSL);
|
||||
}
|
||||
|
||||
mLatestResult.setData(ocVersion);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
mLatestResult = new RemoteOperationResult<>(getMethod);
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
mLatestResult = new RemoteOperationResult<>(
|
||||
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
||||
|
||||
} catch (Exception e) {
|
||||
mLatestResult = new RemoteOperationResult<>(e);
|
||||
}
|
||||
|
||||
if (mLatestResult.isSuccess()) {
|
||||
Log_OC.i(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage());
|
||||
|
||||
} else if (mLatestResult.getException() != null) {
|
||||
Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(),
|
||||
mLatestResult.getException());
|
||||
|
||||
} else {
|
||||
Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private boolean isOnline() {
|
||||
ConnectivityManager cm = (ConnectivityManager) mContext
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
return cm != null && cm.getActiveNetworkInfo() != null
|
||||
&& cm.getActiveNetworkInfo().isConnectedOrConnecting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<OwnCloudVersion> run(OwnCloudClient client) {
|
||||
if (!isOnline()) {
|
||||
return new RemoteOperationResult<>(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
|
||||
}
|
||||
String baseUriStr = client.getBaseUri().toString();
|
||||
if (baseUriStr.startsWith(HTTP_PREFIX) || baseUriStr.startsWith(HTTPS_PREFIX)) {
|
||||
tryConnection(client);
|
||||
|
||||
} else {
|
||||
client.setBaseUri(Uri.parse(HTTPS_PREFIX + baseUriStr));
|
||||
boolean httpsSuccess = tryConnection(client);
|
||||
if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) {
|
||||
Log_OC.d(TAG, "establishing secure connection failed, trying non secure connection");
|
||||
client.setBaseUri(Uri.parse(HTTP_PREFIX + baseUriStr));
|
||||
tryConnection(client);
|
||||
}
|
||||
}
|
||||
return mLatestResult;
|
||||
}
|
||||
|
||||
private boolean isSuccess(int status) {
|
||||
return (status == HttpConstants.HTTP_OK);
|
||||
}
|
||||
}
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* @author masensio
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.status;
|
||||
|
||||
/**
|
||||
* Contains data of the Capabilities for an account, from the Capabilities API
|
||||
*/
|
||||
public class OCCapability {
|
||||
|
||||
private static final String TAG = OCCapability.class.getSimpleName();
|
||||
|
||||
private long mId;
|
||||
private String mAccountName;
|
||||
|
||||
// Server version
|
||||
private int mVersionMayor;
|
||||
private int mVersionMinor;
|
||||
private int mVersionMicro;
|
||||
private String mVersionString;
|
||||
private String mVersionEdition;
|
||||
|
||||
// Core PollInterval
|
||||
private int mCorePollinterval;
|
||||
|
||||
// Files Sharing
|
||||
private CapabilityBooleanType mFilesSharingApiEnabled;
|
||||
|
||||
private CapabilityBooleanType mFilesSharingPublicEnabled;
|
||||
private CapabilityBooleanType mFilesSharingPublicPasswordEnforced;
|
||||
private CapabilityBooleanType mFilesSharingPublicExpireDateEnabled;
|
||||
private int mFilesSharingPublicExpireDateDays;
|
||||
private CapabilityBooleanType mFilesSharingPublicExpireDateEnforced;
|
||||
private CapabilityBooleanType mFilesSharingPublicSendMail;
|
||||
private CapabilityBooleanType mFilesSharingPublicUpload;
|
||||
private CapabilityBooleanType mFilesSharingPublicMultiple;
|
||||
private CapabilityBooleanType mFilesSharingPublicSupportsUploadOnly;
|
||||
|
||||
private CapabilityBooleanType mFilesSharingUserSendMail;
|
||||
|
||||
private CapabilityBooleanType mFilesSharingResharing;
|
||||
|
||||
private CapabilityBooleanType mFilesSharingFederationOutgoing;
|
||||
private CapabilityBooleanType mFilesSharingFederationIncoming;
|
||||
|
||||
// Files
|
||||
private CapabilityBooleanType mFilesBigFileChuncking;
|
||||
private CapabilityBooleanType mFilesUndelete;
|
||||
private CapabilityBooleanType mFilesVersioning;
|
||||
|
||||
public OCCapability() {
|
||||
mId = 0;
|
||||
mAccountName = "";
|
||||
|
||||
mVersionMayor = 0;
|
||||
mVersionMinor = 0;
|
||||
mVersionMicro = 0;
|
||||
mVersionString = "";
|
||||
mVersionString = "";
|
||||
|
||||
mCorePollinterval = 0;
|
||||
|
||||
mFilesSharingApiEnabled = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicEnabled = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicPasswordEnforced = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicExpireDateEnabled = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicExpireDateDays = 0;
|
||||
mFilesSharingPublicExpireDateEnforced = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicSendMail = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicUpload = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicMultiple = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingPublicSupportsUploadOnly = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingUserSendMail = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingResharing = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingFederationOutgoing = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesSharingFederationIncoming = CapabilityBooleanType.UNKNOWN;
|
||||
|
||||
mFilesBigFileChuncking = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesUndelete = CapabilityBooleanType.UNKNOWN;
|
||||
mFilesVersioning = CapabilityBooleanType.UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
// Getters and Setters
|
||||
public String getAccountName() {
|
||||
return mAccountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.mAccountName = accountName;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.mId = id;
|
||||
}
|
||||
|
||||
public int getVersionMayor() {
|
||||
return mVersionMayor;
|
||||
}
|
||||
|
||||
public void setVersionMayor(int versionMayor) {
|
||||
this.mVersionMayor = versionMayor;
|
||||
}
|
||||
|
||||
public int getVersionMinor() {
|
||||
return mVersionMinor;
|
||||
}
|
||||
|
||||
public void setVersionMinor(int versionMinor) {
|
||||
this.mVersionMinor = versionMinor;
|
||||
}
|
||||
|
||||
public int getVersionMicro() {
|
||||
return mVersionMicro;
|
||||
}
|
||||
|
||||
public void setVersionMicro(int versionMicro) {
|
||||
this.mVersionMicro = versionMicro;
|
||||
}
|
||||
|
||||
public String getVersionString() {
|
||||
return mVersionString;
|
||||
}
|
||||
|
||||
public void setVersionString(String versionString) {
|
||||
this.mVersionString = versionString;
|
||||
}
|
||||
|
||||
public String getVersionEdition() {
|
||||
return mVersionEdition;
|
||||
}
|
||||
|
||||
public void setVersionEdition(String versionEdition) {
|
||||
this.mVersionEdition = versionEdition;
|
||||
}
|
||||
|
||||
|
||||
public int getCorePollinterval() {
|
||||
return mCorePollinterval;
|
||||
}
|
||||
|
||||
public void setCorePollinterval(int corePollinterval) {
|
||||
this.mCorePollinterval = corePollinterval;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingApiEnabled() {
|
||||
return mFilesSharingApiEnabled;
|
||||
}
|
||||
|
||||
public void setFilesSharingApiEnabled(CapabilityBooleanType filesSharingApiEnabled) {
|
||||
this.mFilesSharingApiEnabled = filesSharingApiEnabled;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicEnabled() {
|
||||
return mFilesSharingPublicEnabled;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicEnabled(CapabilityBooleanType filesSharingPublicEnabled) {
|
||||
this.mFilesSharingPublicEnabled = filesSharingPublicEnabled;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicPasswordEnforced() {
|
||||
return mFilesSharingPublicPasswordEnforced;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicPasswordEnforced(CapabilityBooleanType filesSharingPublicPasswordEnforced) {
|
||||
this.mFilesSharingPublicPasswordEnforced = filesSharingPublicPasswordEnforced;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicExpireDateEnabled() {
|
||||
return mFilesSharingPublicExpireDateEnabled;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicExpireDateEnabled(CapabilityBooleanType filesSharingPublicExpireDateEnabled) {
|
||||
this.mFilesSharingPublicExpireDateEnabled = filesSharingPublicExpireDateEnabled;
|
||||
}
|
||||
|
||||
public int getFilesSharingPublicExpireDateDays() {
|
||||
return mFilesSharingPublicExpireDateDays;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicExpireDateDays(int filesSharingPublicExpireDateDays) {
|
||||
this.mFilesSharingPublicExpireDateDays = filesSharingPublicExpireDateDays;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicExpireDateEnforced() {
|
||||
return mFilesSharingPublicExpireDateEnforced;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicExpireDateEnforced(CapabilityBooleanType filesSharingPublicExpireDateEnforced) {
|
||||
this.mFilesSharingPublicExpireDateEnforced = filesSharingPublicExpireDateEnforced;
|
||||
}
|
||||
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicSendMail() {
|
||||
return mFilesSharingPublicSendMail;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicSendMail(CapabilityBooleanType filesSharingPublicSendMail) {
|
||||
this.mFilesSharingPublicSendMail = filesSharingPublicSendMail;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicUpload() {
|
||||
return mFilesSharingPublicUpload;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicUpload(CapabilityBooleanType filesSharingPublicUpload) {
|
||||
this.mFilesSharingPublicUpload = filesSharingPublicUpload;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicMultiple() {
|
||||
return mFilesSharingPublicMultiple;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicMultiple(CapabilityBooleanType filesSharingPublicMultiple) {
|
||||
this.mFilesSharingPublicMultiple = filesSharingPublicMultiple;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingPublicSupportsUploadOnly() {
|
||||
return mFilesSharingPublicSupportsUploadOnly;
|
||||
}
|
||||
|
||||
public void setFilesSharingPublicSupportsUploadOnly(CapabilityBooleanType
|
||||
filesSharingPublicMultiple) {
|
||||
this.mFilesSharingPublicSupportsUploadOnly = filesSharingPublicMultiple;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingUserSendMail() {
|
||||
return mFilesSharingUserSendMail;
|
||||
}
|
||||
|
||||
public void setFilesSharingUserSendMail(CapabilityBooleanType filesSharingUserSendMail) {
|
||||
this.mFilesSharingUserSendMail = filesSharingUserSendMail;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingResharing() {
|
||||
return mFilesSharingResharing;
|
||||
}
|
||||
|
||||
public void setFilesSharingResharing(CapabilityBooleanType filesSharingResharing) {
|
||||
this.mFilesSharingResharing = filesSharingResharing;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingFederationOutgoing() {
|
||||
return mFilesSharingFederationOutgoing;
|
||||
}
|
||||
|
||||
public void setFilesSharingFederationOutgoing(CapabilityBooleanType filesSharingFederationOutgoing) {
|
||||
this.mFilesSharingFederationOutgoing = filesSharingFederationOutgoing;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesSharingFederationIncoming() {
|
||||
return mFilesSharingFederationIncoming;
|
||||
}
|
||||
|
||||
public void setFilesSharingFederationIncoming(CapabilityBooleanType filesSharingFederationIncoming) {
|
||||
this.mFilesSharingFederationIncoming = filesSharingFederationIncoming;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesBigFileChuncking() {
|
||||
return mFilesBigFileChuncking;
|
||||
}
|
||||
|
||||
public void setFilesBigFileChuncking(CapabilityBooleanType filesBigFileChuncking) {
|
||||
this.mFilesBigFileChuncking = filesBigFileChuncking;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesUndelete() {
|
||||
return mFilesUndelete;
|
||||
}
|
||||
|
||||
public void setFilesUndelete(CapabilityBooleanType filesUndelete) {
|
||||
this.mFilesUndelete = filesUndelete;
|
||||
}
|
||||
|
||||
public CapabilityBooleanType getFilesVersioning() {
|
||||
return mFilesVersioning;
|
||||
}
|
||||
|
||||
public void setFilesVersioning(CapabilityBooleanType filesVersioning) {
|
||||
this.mFilesVersioning = filesVersioning;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user