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

Merge pull request #173 from owncloud/oauth2_support

OAuth2 support
This commit is contained in:
David A. Velasco 2017-08-23 16:56:13 +02:00 committed by GitHub
commit 2289358775
44 changed files with 1773 additions and 629 deletions

View File

@ -35,7 +35,7 @@ import java.util.List;
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
import com.owncloud.android.lib.resources.files.RemoteFile; import com.owncloud.android.lib.resources.files.RemoteFile;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;

View File

@ -29,6 +29,8 @@ import java.io.IOException;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; 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.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
@ -122,10 +124,10 @@ public class OwnCloudAccount {
throw new IllegalArgumentException("Parameter 'context' cannot be null"); throw new IllegalArgumentException("Parameter 'context' cannot be null");
} }
if (mSavedAccount != null) { if (mSavedAccount != null) {
mCredentials = AccountUtils.getCredentialsForAccount(context, mSavedAccount); mCredentials = AccountUtils.getCredentialsForAccount(context, mSavedAccount);
} }
} }
public Uri getBaseUri() { public Uri getBaseUri() {
return mBaseUri; return mBaseUri;

View File

@ -1,75 +0,0 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import com.owncloud.android.lib.common.network.BearerAuthScheme;
import com.owncloud.android.lib.common.network.BearerCredentials;
public class OwnCloudBearerCredentials implements OwnCloudCredentials {
private String mAccessToken;
public OwnCloudBearerCredentials(String accessToken) {
mAccessToken = accessToken != null ? accessToken : "";
}
@Override
public void applyTo(OwnCloudClient client) {
AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
List<String> authPrefs = new ArrayList<String>(1);
authPrefs.add(BearerAuthScheme.AUTH_POLICY);
client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
client.getParams().setAuthenticationPreemptive(true);
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
client.getState().setCredentials(
AuthScope.ANY,
new BearerCredentials(mAccessToken)
);
}
@Override
public String getUsername() {
// its unknown
return null;
}
@Override
public String getAuthToken() {
return mAccessToken;
}
@Override
public boolean authTokenExpires() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2017 ownCloud GmbH.
* Copyright (C) 2012 Bartek Przybylski * Copyright (C) 2012 Bartek Przybylski
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
@ -33,7 +33,6 @@ import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.HttpStatus;
@ -41,23 +40,27 @@ import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.params.HttpParams; import org.apache.commons.httpclient.params.HttpParams;
import android.accounts.AccountManager;
import android.accounts.AccountsException;
import android.content.Context;
import android.net.Uri; import android.net.Uri;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials; 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.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.network.RedirectionPath; import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
public class OwnCloudClient extends HttpClient { public class OwnCloudClient extends HttpClient {
private static final String TAG = OwnCloudClient.class.getSimpleName(); private static final String TAG = OwnCloudClient.class.getSimpleName();
public static final int MAX_REDIRECTIONS_COUNT = 3; private static final int MAX_REDIRECTIONS_COUNT = 3;
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
private static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; private static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true; private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true;
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version"; private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
@ -73,6 +76,25 @@ public class OwnCloudClient extends HttpClient {
private OwnCloudVersion mVersion = null; private OwnCloudVersion mVersion = null;
/// next too attributes are a very ugly dependency, added to grant silent retry of OAuth token when needed ;
/// see #shouldInvalidateCredentials and #invalidateCredentials for more details
private Context mContext;
private OwnCloudAccount mAccount;
/**
* {@link @OwnCloudClientManager} holding a reference to this object and delivering it to callers; might be
* NULL
*/
private OwnCloudClientManager mOwnCloudClientManager = null;
/**
* When 'true', the method {@link #executeMethod(HttpMethod)} tries to silently refresh credentials
* if fails due to lack of authorization, if credentials support authorization refresh.
*/
private boolean mSilentRefreshOfAccountCredentials = true;
private String mRedirectedLocation;
/** /**
* Constructor * Constructor
*/ */
@ -142,28 +164,6 @@ public class OwnCloudClient extends HttpClient {
mCredentials.applyTo(this); mCredentials.applyTo(this);
} }
/**
* Check if a file exists in the OC server
*
* @return 'true' if the file exists; 'false' it doesn't exist
* @throws Exception When the existence could not be determined
* @deprecated Use ExistenceCheckOperation instead
*/
@Deprecated
public boolean existsFile(String path) throws IOException, HttpException {
HeadMethod head = new HeadMethod(getWebdavUri() + WebdavUtils.encodePath(path));
try {
int status = executeMethod(head);
Log_OC.d(TAG, "HEAD to " + path + " finished with HTTP status " + status +
((status != HttpStatus.SC_OK) ? "(FAIL)" : ""));
exhaustResponse(head.getResponseBodyAsStream());
return (status == HttpStatus.SC_OK);
} finally {
head.releaseConnection(); // let the connection available for other methods
}
}
/** /**
* Requests the received method with the received timeout (milliseconds). * Requests the received method with the received timeout (milliseconds).
* *
@ -207,25 +207,40 @@ public class OwnCloudClient extends HttpClient {
*/ */
@Override @Override
public int executeMethod(HttpMethod method) throws IOException { public int executeMethod(HttpMethod method) throws IOException {
// Update User Agent
HttpParams params = method.getParams();
String userAgent = OwnCloudClientManagerFactory.getUserAgent();
params.setParameter(HttpMethodParams.USER_AGENT, userAgent);
preventCrashDueToInvalidPort(method); boolean repeatWithFreshCredentials;
int repeatCounter = 0;
int status;
Log_OC.d(TAG + " #" + mInstanceNumber, "REQUEST " + do {
// Update User Agent
HttpParams params = method.getParams();
String userAgent = OwnCloudClientManagerFactory.getUserAgent();
params.setParameter(HttpMethodParams.USER_AGENT, userAgent);
preventCrashDueToInvalidPort(method);
Log_OC.d(TAG + " #" + mInstanceNumber, "REQUEST " +
method.getName() + " " + method.getPath()); method.getName() + " " + method.getPath());
//logCookiesAtRequest(method.getRequestHeaders(), "before"); //logCookiesAtRequest(method.getRequestHeaders(), "before");
//logCookiesAtState("before"); //logCookiesAtState("before");
method.setFollowRedirects(false); method.setFollowRedirects(false);
int status = super.executeMethod(method); status = super.executeMethod(method);
if (mFollowRedirects) { checkFirstRedirection(method);
status = followRedirection(method).getLastStatus();
} if (mFollowRedirects) {
status = followRedirection(method).getLastStatus();
}
repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter);
if (repeatWithFreshCredentials) {
repeatCounter++;
}
} while (repeatWithFreshCredentials);
//logCookiesAtRequest(method.getRequestHeaders(), "after"); //logCookiesAtRequest(method.getRequestHeaders(), "after");
//logCookiesAtState("after"); //logCookiesAtState("after");
@ -234,6 +249,17 @@ public class OwnCloudClient extends HttpClient {
return status; return status;
} }
private void checkFirstRedirection(HttpMethod method) {
Header[] httpHeaders = method.getResponseHeaders();
for (Header httpHeader : httpHeaders) {
if ("location".equals(httpHeader.getName().toLowerCase())) {
mRedirectedLocation = httpHeader.getValue();
break;
}
}
}
/** /**
* Fix for https://github.com/owncloud/android/issues/1847#issuecomment-267558274 * Fix for https://github.com/owncloud/android/issues/1847#issuecomment-267558274
@ -266,6 +292,7 @@ public class OwnCloudClient extends HttpClient {
int redirectionsCount = 0; int redirectionsCount = 0;
int status = method.getStatusCode(); int status = method.getStatusCode();
RedirectionPath result = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT); RedirectionPath result = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT);
while (redirectionsCount < MAX_REDIRECTIONS_COUNT && while (redirectionsCount < MAX_REDIRECTIONS_COUNT &&
(status == HttpStatus.SC_MOVED_PERMANENTLY || (status == HttpStatus.SC_MOVED_PERMANENTLY ||
status == HttpStatus.SC_MOVED_TEMPORARILY || status == HttpStatus.SC_MOVED_TEMPORARILY ||
@ -277,10 +304,11 @@ public class OwnCloudClient extends HttpClient {
location = method.getResponseHeader("location"); location = method.getResponseHeader("location");
} }
if (location != null) { if (location != null) {
Log_OC.d(TAG + " #" + mInstanceNumber,
"Location to redirect: " + location.getValue());
String locationStr = location.getValue(); String locationStr = location.getValue();
Log_OC.d(TAG + " #" + mInstanceNumber,
"Location to redirect: " + locationStr);
result.addLocation(locationStr); result.addLocation(locationStr);
// Release the connection to avoid reach the max number of connections per host // Release the connection to avoid reach the max number of connections per host
@ -468,4 +496,138 @@ public class OwnCloudClient extends HttpClient {
public OwnCloudVersion getOwnCloudVersion() { public OwnCloudVersion getOwnCloudVersion() {
return mVersion; return mVersion;
} }
public void setContext(Context context) {
this.mContext = context;
}
public Context getContext() {
return mContext;
}
public void setAccount(OwnCloudAccount account) {
this.mAccount = account;
}
public OwnCloudAccount getAccount() {
return mAccount;
}
/**
* Enables or disables silent refresh of credentials, if supported by credentials themselves.
*/
public void setSilentRefreshOfAccountCredentials(boolean silentRefreshOfAccountCredentials) {
mSilentRefreshOfAccountCredentials = silentRefreshOfAccountCredentials;
}
public boolean getSilentRefreshOfAccountCredentials() {
return mSilentRefreshOfAccountCredentials;
}
/**
* 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(mContext);
// 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: execute 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 == HttpStatus.SC_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 && mContext != 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(mContext);
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")));
}
} }

View File

@ -41,6 +41,7 @@ import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
@ -57,11 +58,12 @@ public class OwnCloudClientFactory {
/** /**
* Creates a OwnCloudClient setup for an ownCloud account * Creates a OwnCloudClient setup for an ownCloud account
* *
* Do not call this method from the main thread. * Do not call this method from the main thread.
* *
* @param account The ownCloud account * @param account The ownCloud account
* @param appContext Android application context * @param appContext Android application context
* @param currentActivity Caller {@link Activity}
* @return A OwnCloudClient object ready to be used * @return A OwnCloudClient object ready to be used
* @throws AuthenticatorException If the authenticator failed to get the authorization * @throws AuthenticatorException If the authenticator failed to get the authorization
* token for the account. * token for the account.
@ -71,69 +73,7 @@ public class OwnCloudClientFactory {
* authorization token for the account. * authorization token for the account.
* @throws AccountNotFoundException If 'account' is unknown for the AccountManager * @throws AccountNotFoundException If 'account' is unknown for the AccountManager
* *
* @deprecated : Will be deleted in version 1.0.
* Use {@link #createOwnCloudClient(Account, Context, Activity)} instead.
*/ */
@Deprecated
public static OwnCloudClient createOwnCloudClient (Account account, Context appContext)
throws OperationCanceledException, AuthenticatorException, IOException,
AccountNotFoundException {
//Log_OC.d(TAG, "Creating OwnCloudClient associated to " + account.name);
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) {
String accessToken = am.blockingGetAuthToken(
account,
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
false);
client.setCredentials(
OwnCloudCredentialsFactory.newBearerCredentials(accessToken)
);
} else if (isSamlSso) { // TODO avoid a call to getUserData here
String accessToken = am.blockingGetAuthToken(
account,
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
false);
client.setCredentials(
OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken)
);
} else {
//String password = am.getPassword(account);
String password = am.blockingGetAuthToken(
account,
AccountTypeUtils.getAuthTokenTypePass(account.type),
false);
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;
}
public static OwnCloudClient createOwnCloudClient (Account account, Context appContext, public static OwnCloudClient createOwnCloudClient (Account account, Context appContext,
Activity currentActivity) Activity currentActivity)
throws OperationCanceledException, AuthenticatorException, IOException, throws OperationCanceledException, AuthenticatorException, IOException,
@ -156,12 +96,12 @@ public class OwnCloudClientFactory {
currentActivity, currentActivity,
null, null,
null); null);
Bundle result = future.getResult(); Bundle result = future.getResult();
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN); String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (accessToken == null) throw new AuthenticatorException("WTF!"); if (accessToken == null) throw new AuthenticatorException("WTF!");
client.setCredentials( client.setCredentials(
OwnCloudCredentialsFactory.newBearerCredentials(accessToken) OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken)
); );
} else if (isSamlSso) { // TODO avoid a call to getUserData here } else if (isSamlSso) { // TODO avoid a call to getUserData here
@ -172,7 +112,7 @@ public class OwnCloudClientFactory {
currentActivity, currentActivity,
null, null,
null); null);
Bundle result = future.getResult(); Bundle result = future.getResult();
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN); String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (accessToken == null) throw new AuthenticatorException("WTF!"); if (accessToken == null) throw new AuthenticatorException("WTF!");
@ -193,7 +133,7 @@ public class OwnCloudClientFactory {
null, null,
null null
); );
Bundle result = future.getResult(); Bundle result = future.getResult();
String password = result.getString(AccountManager.KEY_AUTHTOKEN); String password = result.getString(AccountManager.KEY_AUTHTOKEN);
OwnCloudVersion version = AccountUtils.getServerVersionForAccount(account, appContext); OwnCloudVersion version = AccountUtils.getServerVersionForAccount(account, appContext);
@ -205,13 +145,13 @@ public class OwnCloudClientFactory {
) )
); );
} }
// Restore cookies // Restore cookies
AccountUtils.restoreCookies(account, client, appContext); AccountUtils.restoreCookies(account, client, appContext);
return client; return client;
} }
/** /**
* Creates a OwnCloudClient to access a URL and sets the desired parameters for ownCloud * Creates a OwnCloudClient to access a URL and sets the desired parameters for ownCloud
* client connections. * client connections.
@ -236,6 +176,7 @@ public class OwnCloudClientFactory {
OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager()); OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager());
client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT); client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
client.setFollowRedirects(followRedirects); client.setFollowRedirects(followRedirects);
client.setContext(context);
return client; return client;
} }

View File

@ -36,44 +36,47 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import java.io.IOException; import java.io.IOException;
public class SimpleFactoryManager implements OwnCloudClientManager { public class SimpleFactoryManager implements OwnCloudClientManager {
private static final String TAG = SimpleFactoryManager.class.getSimpleName();
@Override private static final String TAG = SimpleFactoryManager.class.getSimpleName();
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException,
IOException {
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : "); @Override
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException,
IOException {
OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
account.getBaseUri(),
context.getApplicationContext(),
true);
Log_OC.v(TAG, " new client {" + OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(
(account.getName() != null ? account.getBaseUri(),
account.getName() : context.getApplicationContext(),
AccountUtils.buildAccountName(account.getBaseUri(), "") true);
) + ", " + client.hashCode() + "}"); Log_OC.v(TAG, " new client {" +
(account.getName() != null ?
account.getName() :
AccountUtils.buildAccountName(account.getBaseUri(), "")
) + ", " + client.hashCode() + "}");
if (account.getCredentials() == null) { if (account.getCredentials() == null) {
account.loadCredentials(context); account.loadCredentials(context);
} }
client.setCredentials(account.getCredentials()); client.setCredentials(account.getCredentials());
return client; client.setAccount(account);
} client.setContext(context);
client.setOwnCloudClientManager(this);
return client;
}
@Override @Override
public OwnCloudClient removeClientFor(OwnCloudAccount account) { public OwnCloudClient removeClientFor(OwnCloudAccount account) {
// nothing to do - not taking care of tracking instances! // nothing to do - not taking care of tracking instances!
return null; return null;
} }
@Override @Override
public void saveAllClients(Context context, String accountType) { public void saveAllClients(Context context, String accountType) {
// nothing to do - not taking care of tracking instances! // nothing to do - not taking care of tracking instances!
} }
} }

View File

@ -40,6 +40,7 @@ import android.util.Log;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
/** /**
@ -115,8 +116,11 @@ public class SingleSessionManager implements OwnCloudClientManager {
context.getApplicationContext(), context.getApplicationContext(),
true); // TODO remove dependency on OwnCloudClientFactory true); // TODO remove dependency on OwnCloudClientFactory
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
// enable cookie tracking client.setAccount(account);
client.setContext(context);
client.setOwnCloudClientManager(this);
// enable cookie tracking
AccountUtils.restoreCookies(account.getSavedAccount(), client, context); AccountUtils.restoreCookies(account.getSavedAccount(), client, context);
account.loadCredentials(context); account.loadCredentials(context);

View File

@ -28,6 +28,7 @@ package com.owncloud.android.lib.common.accounts;
import java.io.IOException; import java.io.IOException;
import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpStatus;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
@ -37,9 +38,12 @@ import android.accounts.OperationCanceledException;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentials; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
@ -53,45 +57,25 @@ public class AccountUtils {
/** /**
* Constructs full url to host and webdav resource basing on host version * Constructs full url to host and webdav resource basing on host version
* *
* @param context * @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
* @param account * @param account A stored ownCloud {@link Account}
* @return url or null on failure * @return Full URL to WebDAV endpoint in the server corresponding to 'account'.
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager * @throws AccountNotFoundException When 'account' is unknown for the AccountManager
* @deprecated To be removed in release 1.0.
*/ */
@Deprecated public static String getWebDavUrlForAccount(Context context, Account account)
public static String constructFullURLForAccount(Context context, Account account) throws AccountNotFoundException {
AccountManager ama = AccountManager.get(context);
String baseurl = ama.getUserData(account, Constants.KEY_OC_BASE_URL);
if (baseurl == null) {
throw new AccountNotFoundException(account, "Account not found", null);
}
return baseurl + WEBDAV_PATH_4_0;
}
/**
* Extracts url server from the account
*
* @param context
* @param account
* @return url server or null on failure
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager
* @deprecated This method will be removed in version 1.0.
* Use {@link #getBaseUrlForAccount(Context, Account)}
* instead.
*/
@Deprecated
public static String constructBasicURLForAccount(Context context, Account account)
throws AccountNotFoundException { throws AccountNotFoundException {
return getBaseUrlForAccount(context, account);
return getBaseUrlForAccount(context, account) + WEBDAV_PATH_4_0;
} }
/** /**
* Extracts url server from the account * Extracts url server from the account
* *
* @param context * @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
* @param account * @param account A stored ownCloud {@link Account}
* @return url server or null on failure * @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 * @throws AccountNotFoundException When 'account' is unknown for the AccountManager
*/ */
public static String getBaseUrlForAccount(Context context, Account account) public static String getBaseUrlForAccount(Context context, Account account)
@ -171,7 +155,7 @@ public class AccountUtils {
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
false); false);
credentials = OwnCloudCredentialsFactory.newBearerCredentials(accessToken); credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
} else if (isSamlSso) { } else if (isSamlSso) {
String accessToken = am.blockingGetAuthToken( String accessToken = am.blockingGetAuthToken(
@ -300,15 +284,6 @@ public class AccountUtils {
public static class Constants { public static class Constants {
/**
* Value under this key should handle path to webdav php script. Will be
* removed and usage should be replaced by combining
* {@link #KEY_OC_BASE_URL } and
* {@link com.owncloud.android.lib.resources.status.OwnCloudVersion}
*
* @deprecated
*/
public static final String KEY_OC_URL = "oc_url";
/** /**
* Version should be 3 numbers separated by dot so it can be parsed by * Version should be 3 numbers separated by dot so it can be parsed by
* {@link com.owncloud.android.lib.resources.status.OwnCloudVersion} * {@link com.owncloud.android.lib.resources.status.OwnCloudVersion}
@ -327,12 +302,6 @@ public class AccountUtils {
* Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on. * 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"; public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
/**
* Flag signaling if the ownCloud server supports Share API"
*
* @deprecated
*/
public static final String KEY_SUPPORTS_SHARE_API = "oc_supports_share_api";
/** /**
* OC account cookies * OC account cookies
*/ */
@ -348,6 +317,11 @@ public class AccountUtils {
*/ */
public static final String KEY_DISPLAY_NAME = "oc_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";
} }
} }

View File

@ -21,7 +21,9 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -29,6 +31,8 @@ import java.util.List;
import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy; import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.auth.AuthState;
import org.apache.commons.httpclient.auth.BasicScheme;
public class OwnCloudBasicCredentials implements OwnCloudCredentials { public class OwnCloudBasicCredentials implements OwnCloudCredentials {
@ -50,6 +54,8 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
@Override @Override
public void applyTo(OwnCloudClient client) { public void applyTo(OwnCloudClient client) {
AuthPolicy.registerAuthScheme(AuthState.PREEMPTIVE_AUTH_SCHEME, BasicScheme.class);
List<String> authPrefs = new ArrayList<String>(1); List<String> authPrefs = new ArrayList<String>(1);
authPrefs.add(AuthPolicy.BASIC); authPrefs.add(AuthPolicy.BASIC);
client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs); client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
@ -77,4 +83,9 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
return false; return false;
} }
@Override
public boolean authTokenCanBeRefreshed() {
return false;
}
} }

View File

@ -0,0 +1,85 @@
/* 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 java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.auth.AuthState;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.authentication.oauth.BearerAuthScheme;
import com.owncloud.android.lib.common.authentication.oauth.BearerCredentials;
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) {
AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
AuthPolicy.registerAuthScheme(AuthState.PREEMPTIVE_AUTH_SCHEME, BearerAuthScheme.class);
List<String> authPrefs = new ArrayList<>(1);
authPrefs.add(BearerAuthScheme.AUTH_POLICY);
client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
client.getParams().setAuthenticationPreemptive(true); // true enforces BASIC AUTH ; library is stupid
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
client.getState().setCredentials(
AuthScope.ANY,
new BearerCredentials(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;
}
}

View File

@ -22,16 +22,19 @@
* *
*/ */
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
public interface OwnCloudCredentials { public interface OwnCloudCredentials {
public void applyTo(OwnCloudClient ownCloudClient); void applyTo(OwnCloudClient ownCloudClient);
public String getUsername(); String getUsername();
public String getAuthToken(); String getAuthToken();
public boolean authTokenExpires(); boolean authTokenExpires();
boolean authTokenCanBeRefreshed();
} }

View File

@ -22,7 +22,9 @@
* *
*/ */
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient;
public class OwnCloudCredentialsFactory { public class OwnCloudCredentialsFactory {
@ -40,8 +42,8 @@ public class OwnCloudCredentialsFactory {
return new OwnCloudBasicCredentials(username, password, preemptiveMode); return new OwnCloudBasicCredentials(username, password, preemptiveMode);
} }
public static OwnCloudCredentials newBearerCredentials(String authToken) { public static OwnCloudCredentials newBearerCredentials(String username, String authToken) {
return new OwnCloudBearerCredentials(authToken); return new OwnCloudBearerCredentials(username, authToken);
} }
public static OwnCloudCredentials newSamlSsoCredentials(String username, String sessionCookie) { public static OwnCloudCredentials newSamlSsoCredentials(String username, String sessionCookie) {
@ -76,6 +78,11 @@ public class OwnCloudCredentialsFactory {
return false; return false;
} }
@Override
public boolean authTokenCanBeRefreshed() {
return false;
}
@Override @Override
public String getUsername() { public String getUsername() {
// no user name // no user name

View File

@ -21,63 +21,70 @@
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common.authentication;
import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.cookie.CookiePolicy;
import android.net.Uri; import android.net.Uri;
import com.owncloud.android.lib.common.OwnCloudClient;
public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials { public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
private String mUsername; private String mUsername;
private String mSessionCookie; private String mSessionCookie;
public OwnCloudSamlSsoCredentials(String username, String sessionCookie) { public OwnCloudSamlSsoCredentials(String username, String sessionCookie) {
mUsername = username != null ? username : ""; mUsername = username != null ? username : "";
mSessionCookie = sessionCookie != null ? sessionCookie : ""; mSessionCookie = sessionCookie != null ? sessionCookie : "";
} }
@Override @Override
public void applyTo(OwnCloudClient client) { public void applyTo(OwnCloudClient client) {
client.getParams().setAuthenticationPreemptive(false); client.getParams().setAuthenticationPreemptive(false);
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET); client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
client.setFollowRedirects(false); client.setFollowRedirects(false);
Uri serverUri = client.getBaseUri(); Uri serverUri = client.getBaseUri();
String[] cookies = mSessionCookie.split(";"); String[] cookies = mSessionCookie.split(";");
if (cookies.length > 0) { if (cookies.length > 0) {
Cookie cookie = null; Cookie cookie = null;
for (int i=0; i<cookies.length; i++) { for (int i = 0; i < cookies.length; i++) {
int equalPos = cookies[i].indexOf('='); int equalPos = cookies[i].indexOf('=');
if (equalPos >= 0) { if (equalPos >= 0) {
cookie = new Cookie(); cookie = new Cookie();
cookie.setName(cookies[i].substring(0, equalPos)); cookie.setName(cookies[i].substring(0, equalPos));
cookie.setValue(cookies[i].substring(equalPos + 1)); cookie.setValue(cookies[i].substring(equalPos + 1));
cookie.setDomain(serverUri.getHost()); // VERY IMPORTANT cookie.setDomain(serverUri.getHost()); // VERY IMPORTANT
cookie.setPath(serverUri.getPath()); // VERY IMPORTANT cookie.setPath(serverUri.getPath()); // VERY IMPORTANT
client.getState().addCookie(cookie); client.getState().addCookie(cookie);
} }
} }
} }
} }
@Override @Override
public String getUsername() { public String getUsername() {
// not relevant for authentication, but relevant for informational purposes // not relevant for authentication, but relevant for informational purposes
return mUsername; return mUsername;
} }
@Override
public String getAuthToken() {
return mSessionCookie;
}
@Override @Override
public boolean authTokenExpires() { public String getAuthToken() {
return true; return mSessionCookie;
} }
@Override
public boolean authTokenExpires() {
return true;
}
@Override
public boolean authTokenCanBeRefreshed() {
return false;
}
} }

View File

@ -22,7 +22,7 @@
* *
*/ */
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.authentication.oauth;
import java.util.Map; import java.util.Map;
@ -34,8 +34,6 @@ import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.auth.InvalidCredentialsException; import org.apache.commons.httpclient.auth.InvalidCredentialsException;
import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.auth.MalformedChallengeException;
import com.owncloud.android.lib.common.utils.Log_OC;
/** /**
@ -71,8 +69,6 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
* @param challenge Authentication challenge * @param challenge Authentication challenge
* *
* @throws MalformedChallengeException Thrown if the authentication challenge is malformed * @throws MalformedChallengeException Thrown if the authentication challenge is malformed
*
* @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} method
*/ */
public BearerAuthScheme(final String challenge) throws MalformedChallengeException { public BearerAuthScheme(final String challenge) throws MalformedChallengeException {
processChallenge(challenge); processChallenge(challenge);
@ -125,13 +121,9 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
* for this authentication scheme * for this authentication scheme
* @throws AuthenticationException If authorization string cannot be generated due to an authentication failure * @throws AuthenticationException If authorization string cannot be generated due to an authentication failure
* @return A bearer authorization string * @return A bearer authorization string
*
* @deprecated Use {@link #authenticate(Credentials, HttpMethod)}
*/ */
public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException { public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
Log_OC.d(TAG, "enter BearerScheme.authenticate(Credentials, String, String)"); BearerCredentials bearer;
BearerCredentials bearer = null;
try { try {
bearer = (BearerCredentials) credentials; bearer = (BearerCredentials) credentials;
} catch (ClassCastException e) { } catch (ClassCastException e) {
@ -164,8 +156,6 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
* @return a basic authorization string * @return a basic authorization string
*/ */
public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
Log_OC.d(TAG, "enter BearerScheme.authenticate(Credentials, HttpMethod)");
if (method == null) { if (method == null) {
throw new IllegalArgumentException("Method may not be null"); throw new IllegalArgumentException("Method may not be null");
} }
@ -183,9 +173,7 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
} }
/** /**
* @deprecated Use {@link #authenticate(BearerCredentials, String)} * Returns a bearer Authorization header value for the given
*
* Returns a bearer Authorization header value for the given
* {@link BearerCredentials}. * {@link BearerCredentials}.
* *
* @param credentials The credentials to encode. * @param credentials The credentials to encode.
@ -208,7 +196,6 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
* @since 3.0 * @since 3.0
*/ */
public static String authenticate(BearerCredentials credentials, String charset) { public static String authenticate(BearerCredentials credentials, String charset) {
Log_OC.d(TAG, "enter BearerAuthScheme.authenticate(BearerCredentials, String)");
if (credentials == null) { if (credentials == null) {
throw new IllegalArgumentException("Credentials may not be null"); throw new IllegalArgumentException("Credentials may not be null");
@ -218,8 +205,7 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
} }
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append(credentials.getAccessToken()); buffer.append(credentials.getAccessToken());
//return "Bearer " + EncodingUtil.getAsciiString(EncodingUtil.getBytes(buffer.toString(), charset));
return "Bearer " + buffer.toString(); return "Bearer " + buffer.toString();
} }
@ -239,8 +225,6 @@ public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
* This method simply returns the realm for the challenge. * This method simply returns the realm for the challenge.
* *
* @return String a String identifying the authentication challenge. * @return String a String identifying the authentication challenge.
*
* @deprecated no longer used
*/ */
@Override @Override
public String getID() { public String getID() {

View File

@ -22,7 +22,7 @@
* *
*/ */
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.authentication.oauth;
import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.util.LangUtils; import org.apache.commons.httpclient.util.LangUtils;

View File

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

View File

@ -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";
}

View File

@ -0,0 +1,148 @@
/* 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.authentication.OwnCloudBasicCredentials;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class OAuth2GetAccessTokenOperation extends RemoteOperation {
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 result = null;
PostMethod postMethod = null;
try {
NameValuePair[] nameValuePairs = new NameValuePair[4];
nameValuePairs[0] = new NameValuePair(OAuth2Constants.KEY_GRANT_TYPE, mGrantType);
nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CODE, mCode);
nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri);
nameValuePairs[3] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
postMethod = new PostMethod(uriBuilder.build().toString());
postMethod.setRequestBody(nameValuePairs);
OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(
mClientId,
mClientSecret
);
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
client.executeMethod(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(true, postMethod);
ArrayList<Object> data = new ArrayList<>();
data.add(accessTokenResult);
result.setData(data);
}
} else {
result = new RemoteOperationResult(false, postMethod);
client.exhaustResponse(postMethod.getResponseBodyAsStream());
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
if (postMethod != null)
postMethod.releaseConnection(); // let the connection available for other methods
}
return result;
}
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
OwnCloudCredentials previousCredentials = getClient().getCredentials();
getClient().setCredentials(newCredentials);
return previousCredentials;
}
}

View File

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

View File

@ -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();
}

View File

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

View File

@ -0,0 +1,73 @@
/* 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();
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;
}
}

View File

@ -0,0 +1,146 @@
/**
* ownCloud Android client application
*
* @author David González Verdugo
*
* 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 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.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.utils.Log_OC;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Map;
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation {
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 run(OwnCloudClient client) {
RemoteOperationResult result = null;
PostMethod postMethod = null;
try {
NameValuePair[] nameValuePairs = new NameValuePair[3];
nameValuePairs[0] = new NameValuePair(
OAuth2Constants.KEY_GRANT_TYPE,
OAuth2GrantType.REFRESH_TOKEN.getValue() // always for this operation
);
nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken);
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
postMethod = new PostMethod(uriBuilder.build().toString());
postMethod.setRequestBody(nameValuePairs);
OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(
mClientId,
mClientSecret
);
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
client.executeMethod(postMethod);
switchClientCredentials(oldCredentials);
String response = postMethod.getResponseBodyAsString();
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + response);
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(true, postMethod);
ArrayList<Object> data = new ArrayList<>();
data.add(accessTokenResult);
result.setData(data);
}
} else {
result = new RemoteOperationResult(false, postMethod);
client.exhaustResponse(postMethod.getResponseBodyAsStream());
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
if (postMethod != null) {
postMethod.releaseConnection(); // let the connection available for other methods
}
}
return result;
}
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
OwnCloudCredentials previousCredentials = getClient().getCredentials();
getClient().setCredentials(newCredentials);
return previousCredentials;
}
}

View File

@ -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();
}

View File

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

View File

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

View File

@ -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"
);
}
}
}

View File

@ -1,5 +1,5 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2017 ownCloud GmbH.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,19 +25,16 @@
package com.owncloud.android.lib.common.operations; package com.owncloud.android.lib.common.operations;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import android.app.Activity; import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudCredentials;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import java.io.IOException; import java.io.IOException;
@ -45,58 +42,69 @@ import java.io.IOException;
/** /**
* Operation which execution involves one or several interactions with an ownCloud server. * Operation which execution involves one or several interactions with an ownCloud server.
* *
* Provides methods to execute the operation both synchronously or asynchronously. * Provides methods to execute the operation both synchronously or asynchronously.
* *
* @author David A. Velasco * @author David A. Velasco
* @author David González Verdugo
*/ */
public abstract class RemoteOperation implements Runnable { public abstract class RemoteOperation implements Runnable {
private static final String TAG = RemoteOperation.class.getSimpleName(); private static final String TAG = RemoteOperation.class.getSimpleName();
/** OCS API header name */ /**
* OCS API header name
*/
public static final String OCS_API_HEADER = "OCS-APIREQUEST"; public static final String OCS_API_HEADER = "OCS-APIREQUEST";
/** OCS API header value */ /**
* OCS API header value
*/
public static final String OCS_API_HEADER_VALUE = "true"; public static final String OCS_API_HEADER_VALUE = "true";
/** ownCloud account in the remote ownCloud server to operate */ /**
* ownCloud account in the remote ownCloud server to operate
*/
private Account mAccount = null; private Account mAccount = null;
/** Android Application context */ /**
* Android Application context
*/
private Context mContext = null; private Context mContext = null;
/** Object to interact with the remote server */
private OwnCloudClient mClient = null;
/** Callback object to notify about the execution of the remote operation */
private OnRemoteOperationListener mListener = null;
/** Handler to the thread where mListener methods will be called */
private Handler mListenerHandler = null;
/** Activity */ /**
private Activity mCallerActivity; * Object to interact with the remote server
*/
private OwnCloudClient mClient = null;
/**
* Callback object to notify about the execution of the remote operation
*/
private OnRemoteOperationListener mListener = null;
/**
* Handler to the thread where mListener methods will be called
*/
private Handler mListenerHandler = null;
/**
* Abstract method to implement the operation in derived classes.
*/
protected abstract RemoteOperationResult run(OwnCloudClient client);
/**
* Abstract method to implement the operation in derived classes.
*/
protected abstract RemoteOperationResult run(OwnCloudClient client);
/** /**
* Synchronously executes the remote operation on the received ownCloud account. * Synchronously executes the remote operation on the received ownCloud account.
* *
* Do not call this method from the main thread. * Do not call this method from the main thread.
* *
* This method should be used whenever an ownCloud account is available, instead of * This method should be used whenever an ownCloud account is available, instead of
* {@link #execute(OwnCloudClient)}. * {@link #execute(OwnCloudClient)}.
* *
* @param account ownCloud account in remote ownCloud server to reach during the * @param account ownCloud account in remote ownCloud server to reach during the
* execution of the operation. * execution of the operation.
* @param context Android context for the component calling the method. * @param context Android context for the component calling the method.
* @return Result of the operation. * @return Result of the operation.
*/ */
public RemoteOperationResult execute(Account account, Context context) { public RemoteOperationResult execute(Account account, Context context) {
if (account == null) if (account == null)
@ -107,258 +115,187 @@ public abstract class RemoteOperation implements Runnable {
"Context"); "Context");
mAccount = account; mAccount = account;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext); return runOperation();
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, mContext);
} catch (Exception e) {
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
return new RemoteOperationResult(e);
}
return run(mClient);
} }
/** /**
* Synchronously executes the remote operation * Synchronously executes the remote operation
* *
* Do not call this method from the main thread. * Do not call this method from the main thread.
* *
* @param client Client object to reach an ownCloud server during the execution of * @param client Client object to reach an ownCloud server during the execution of
* the operation. * the operation.
* @return Result of the operation. * @return Result of the operation.
*/
public RemoteOperationResult execute(OwnCloudClient client) {
if (client == null)
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
"OwnCloudClient");
mClient = client;
return run(client);
}
/**
* Asynchronously executes the remote operation
*
* This method should be used whenever an ownCloud account is available, instead of
* {@link #execute(OwnCloudClient)}.
*
* @deprecated This method will be removed in version 1.0.
* Use {@link #execute(Account, Context, OnRemoteOperationListener,
* Handler)} instead.
*
* @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.
*/ */
@Deprecated public RemoteOperationResult execute(OwnCloudClient client) {
public Thread execute(Account account, Context context, OnRemoteOperationListener listener, if (client == null)
Handler listenerHandler, Activity callerActivity) { throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
if (account == null) "OwnCloudClient");
throw new IllegalArgumentException mClient = client;
("Trying to execute a remote operation with a NULL Account"); if (client.getAccount() != null) {
if (context == null) mAccount = client.getAccount().getSavedAccount();
throw new IllegalArgumentException }
("Trying to execute a remote operation with a NULL Context"); mContext = client.getContext();
mAccount = account;
mContext = context.getApplicationContext(); return runOperation();
mCallerActivity = callerActivity;
mClient = null; // the client instance will be created from mAccount
// and mContext in the runnerThread to create below
mListener = listener;
mListenerHandler = listenerHandler;
Thread runnerThread = new Thread(this);
runnerThread.start();
return runnerThread;
} }
/** /**
* Asynchronously executes the remote operation * Asynchronously executes the remote operation
* *
* This method should be used whenever an ownCloud account is available, * This method should be used whenever an ownCloud account is available,
* instead of {@link #execute(OwnCloudClient, OnRemoteOperationListener, Handler))}. * instead of {@link #execute(OwnCloudClient, OnRemoteOperationListener, Handler))}.
* *
* @param account ownCloud account in remote ownCloud server to reach during the * @param account ownCloud account in remote ownCloud server to reach during the
* execution of the operation. * execution of the operation.
* @param context Android context for the component calling the method. * @param context Android context for the component calling the method.
* @param listener Listener to be notified about the execution of the operation. * @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 * @param listenerHandler Handler associated to the thread where the methods of the listener
* objects must be called. * objects must be called.
* @return Thread were the remote operation is executed. * @return Thread were the remote operation is executed.
*/ */
public Thread execute(Account account, Context context, public Thread execute(Account account, Context context,
OnRemoteOperationListener listener, Handler listenerHandler) { OnRemoteOperationListener listener, Handler listenerHandler) {
if (account == null) if (account == null)
throw new IllegalArgumentException throw new IllegalArgumentException
("Trying to execute a remote operation with a NULL Account"); ("Trying to execute a remote operation with a NULL Account");
if (context == null) if (context == null)
throw new IllegalArgumentException throw new IllegalArgumentException
("Trying to execute a remote operation with a NULL Context"); ("Trying to execute a remote operation with a NULL Context");
// mAccount and mContext in the runnerThread to create below
mAccount = account; mAccount = account;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mCallerActivity = null;
mClient = null; // the client instance will be created from mClient = null; // the client instance will be created from
// mAccount and mContext in the runnerThread to create below
mListener = listener; mListener = listener;
mListenerHandler = listenerHandler; mListenerHandler = listenerHandler;
Thread runnerThread = new Thread(this); Thread runnerThread = new Thread(this);
runnerThread.start(); runnerThread.start();
return runnerThread; return runnerThread;
} }
/** /**
* Asynchronously executes the remote operation * Asynchronously executes the remote operation
* *
* @param client Client object to reach an ownCloud server * @param client Client object to reach an ownCloud server
* during the execution of the operation. * during the execution of the operation.
* @param listener Listener to be notified about 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 * @param listenerHandler Handler, if passed in, associated to the thread where the methods of
* the listener objects must be called. * the listener objects must be called.
* @return Thread were the remote operation is executed. * @return Thread were the remote operation is executed.
*/ */
public Thread execute(OwnCloudClient client, public Thread execute(OwnCloudClient client,
OnRemoteOperationListener listener, Handler listenerHandler) { OnRemoteOperationListener listener, Handler listenerHandler) {
if (client == null) { if (client == null) {
throw new IllegalArgumentException throw new IllegalArgumentException
("Trying to execute a remote operation with a NULL OwnCloudClient"); ("Trying to execute a remote operation with a NULL OwnCloudClient");
} }
mClient = client; mClient = client;
if (client.getAccount() != null) {
if (listener == null) { mAccount = client.getAccount().getSavedAccount();
throw new IllegalArgumentException }
mContext = client.getContext();
if (listener == null) {
throw new IllegalArgumentException
("Trying to execute a remote operation asynchronously " + ("Trying to execute a remote operation asynchronously " +
"without a listener to notiy the result"); "without a listener to notiy the result");
} }
mListener = listener; mListener = listener;
if (listenerHandler != null) { if (listenerHandler != null) {
mListenerHandler = listenerHandler; mListenerHandler = listenerHandler;
} }
Thread runnerThread = new Thread(this);
Thread runnerThread = new Thread(this); runnerThread.start();
runnerThread.start(); return runnerThread;
return runnerThread; }
}
/** /**
* Asynchronous execution of the operation * Asynchronous execution of the operation
* started by {@link RemoteOperation#execute(OwnCloudClient, * started by {@link RemoteOperation#execute(OwnCloudClient,
* OnRemoteOperationListener, Handler)}, * OnRemoteOperationListener, Handler)},
* and result posting. * and result posting.
* */
* TODO refactor && clean the code; now it's a mess
*/
@Override @Override
public final void run() { public final void run() {
RemoteOperationResult result = null;
boolean repeat = false; final RemoteOperationResult resultToSend = runOperation();
do {
try{
if (mClient == null) {
if (mAccount != null && mContext != null) {
/** DEPRECATED BLOCK - will be removed at version 1.0 */
if (mCallerActivity != null) {
mClient = OwnCloudClientFactory.createOwnCloudClient(
mAccount, mContext, mCallerActivity);
} else {
/** EOF DEPRECATED */
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 instance or account");
}
}
} catch (IOException e) {
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name,
new AccountsException("I/O exception while trying to authorize the account",
e));
result = new RemoteOperationResult(e);
} catch (AccountsException e) {
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
result = new RemoteOperationResult(e);
}
if (result == null)
result = run(mClient);
repeat = false;
/** DEPRECATED BLOCK - will be removed at version 1.0 ; don't trust in this code
* to trigger authentication update */
if (mCallerActivity != null && mAccount != null && mContext != null &&
!result.isSuccess() &&
ResultCode.UNAUTHORIZED.equals(result.getCode())
) {
/// possible fail due to lack of authorization
// in an operation performed in foreground
OwnCloudCredentials cred = mClient.getCredentials();
if (cred != null) {
/// confirmed : unauthorized operation
AccountManager am = AccountManager.get(mContext);
if (cred.authTokenExpires()) {
am.invalidateAuthToken(
mAccount.type,
cred.getAuthToken()
);
} else {
am.clearPassword(mAccount);
}
mClient = null;
// when repeated, the creation of a new OwnCloudClient after erasing the saved
// credentials will trigger the login activity
repeat = true;
result = null;
}
}
/** EOF DEPRECATED BLOCK **/
} while (repeat);
if (mAccount != null && mContext != null) { if (mAccount != null && mContext != null) {
// Save Client Cookies // Save Client Cookies
AccountUtils.saveClient(mClient, mAccount, mContext); AccountUtils.saveClient(mClient, mAccount, mContext);
} }
final RemoteOperationResult resultToSend = result;
if (mListenerHandler != null && mListener != null) { if (mListenerHandler != null && mListener != null) {
mListenerHandler.post(new Runnable() { mListenerHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend); mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
} }
}); });
} } else if (mListener != null) {
else if(mListener != null) {
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend); mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
} }
} }
/**
* Run operation for asynchronous or synchronous 'execute' 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 runOperation() {
RemoteOperationResult 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;
}
private void grantOwnCloudClient() throws
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
if (mClient == null) {
if (mAccount != null && mContext != null) {
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
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. * Returns the current client instance to access the remote server.
* *
* @return Current client instance to access the remote server. * @return Current client instance to access the remote server.
*/ */
public final OwnCloudClient getClient() { public final OwnCloudClient getClient() {
return mClient; return mClient;
} }
} }

View File

@ -129,7 +129,7 @@ public class RemoteOperationResult implements Serializable {
private Exception mException = null; private Exception mException = null;
private ResultCode mCode = ResultCode.UNKNOWN_ERROR; private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
private String mRedirectedLocation; private String mRedirectedLocation;
private String mAuthenticate; private ArrayList<String> mAuthenticate = new ArrayList<>();
private String mLastPermanentLocation = null; private String mLastPermanentLocation = null;
private ArrayList<Object> mData; private ArrayList<Object> mData;
@ -313,16 +313,13 @@ public class RemoteOperationResult implements Serializable {
public RemoteOperationResult(boolean success, int httpCode, String httpPhrase, Header[] httpHeaders) { public RemoteOperationResult(boolean success, int httpCode, String httpPhrase, Header[] httpHeaders) {
this(success, httpCode, httpPhrase); this(success, httpCode, httpPhrase);
if (httpHeaders != null) { if (httpHeaders != null) {
Header current;
for (Header httpHeader : httpHeaders) { for (Header httpHeader : httpHeaders) {
current = httpHeader; if ("location".equals(httpHeader.getName().toLowerCase())) {
if ("location".equals(current.getName().toLowerCase())) { mRedirectedLocation = httpHeader.getValue();
mRedirectedLocation = current.getValue();
continue; continue;
} }
if ("www-authenticate".equals(current.getName().toLowerCase())) { if ("www-authenticate".equals(httpHeader.getName().toLowerCase())) {
mAuthenticate = current.getValue(); mAuthenticate.add(httpHeader.getValue().toLowerCase());
break;
} }
} }
} }
@ -562,7 +559,7 @@ public class RemoteOperationResult implements Serializable {
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://"))); return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
} }
public String getAuthenticateHeader() { public ArrayList<String> getAuthenticateHeaders() {
return mAuthenticate; return mAuthenticate;
} }

View File

@ -71,19 +71,6 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
mSuccessIfAbsent = successIfAbsent; mSuccessIfAbsent = successIfAbsent;
} }
/**
* 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 context Android application context.
* @param successIfAbsent When 'true', the operation finishes in success if the path does
* NOT exist in the remote server (HTTP 404).
* @deprecated
*/
public ExistenceCheckRemoteOperation(String remotePath, Context context, boolean successIfAbsent) {
this(remotePath, successIfAbsent);
}
@Override @Override
protected RemoteOperationResult run(OwnCloudClient client) { protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult result = null; RemoteOperationResult result = null;

View File

@ -24,6 +24,8 @@
package com.owncloud.android.lib.resources.files; package com.owncloud.android.lib.resources.files;
import android.os.RemoteException;
import java.io.File; import java.io.File;
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase; import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
@ -101,8 +103,7 @@ public class RenameRemoteFileOperation extends RemoteOperation {
return new RemoteOperationResult(ResultCode.OK); return new RemoteOperationResult(ResultCode.OK);
} }
// check if a file with the new name already exists if (targetPathIsUsed(client)) {
if (client.existsFile(mNewRemotePath)) {
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE); return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
} }
@ -134,6 +135,18 @@ public class RenameRemoteFileOperation extends RemoteOperation {
return result; 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);
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
return exists.isSuccess();
}
/** /**
* Move operation * Move operation
*/ */

View File

@ -63,14 +63,6 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
private int mVersion; private int mVersion;
private boolean mIsValid; private boolean mIsValid;
/**
* @deprecated Will be removed in version 1.0 of the library.
*/
private OwnCloudVersion(int version) {
mVersion = version;
mIsValid = true;
}
public OwnCloudVersion(String version) { public OwnCloudVersion(String version) {
mVersion = 0; mVersion = 0;
mIsValid = false; mIsValid = false;

View File

@ -28,7 +28,7 @@
package com.owncloud.android.lib.resources.users; package com.owncloud.android.lib.resources.users;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentials; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;

View File

@ -25,9 +25,9 @@
<resources> <resources>
<string name="build_number"></string> <string name="build_number"></string>
<string name="server_base_url"></string> <string name="server_base_url">https://qa.oc.solidgear.es</string>
<string name="server_base_url_2"></string> <string name="server_base_url_2">https://qa2.oc.solidgear.es</string>
<string name="username"></string> <string name="username">android-library-test</string>
<string name="password"></string> <string name="password">letitgo,letitgo,thatperfectappisgone</string>
<string name ="user_agent">Mozilla/5.0 (Android) ownCloud test project</string> <string name ="user_agent">Mozilla/5.0 (Android) ownCloud test project</string>
</resources> </resources>

View File

@ -42,7 +42,7 @@ import android.view.Menu;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;

View File

@ -31,7 +31,7 @@ import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;

View File

@ -38,7 +38,7 @@ import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation; import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation;

View File

@ -37,7 +37,7 @@ import org.json.JSONObject;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation; import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation;

View File

@ -35,7 +35,7 @@ import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;

View File

@ -43,9 +43,9 @@ import android.test.AndroidTestCase;
import android.util.Log; import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentials;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.test_project.R; import com.owncloud.android.lib.test_project.R;
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
@ -130,7 +130,7 @@ public class OwnCloudClientTest extends AndroidTestCase {
client.setCredentials(credentials); client.setCredentials(credentials);
assertEquals("Basic credentials not set", credentials, client.getCredentials()); assertEquals("Basic credentials not set", credentials, client.getCredentials());
credentials = OwnCloudCredentialsFactory.newBearerCredentials("bearerToken"); credentials = OwnCloudCredentialsFactory.newBearerCredentials("user", "bearerToken");
client.setCredentials(credentials); client.setCredentials(credentials);
assertEquals("Bearer credentials not set", credentials, client.getCredentials()); assertEquals("Bearer credentials not set", credentials, client.getCredentials());
@ -294,7 +294,7 @@ public class OwnCloudClientTest extends AndroidTestCase {
public void testGetWebdavUri() { public void testGetWebdavUri() {
OwnCloudClient client = OwnCloudClient client =
new OwnCloudClient(mServerUri, NetworkUtils.getMultiThreadedConnManager()); new OwnCloudClient(mServerUri, NetworkUtils.getMultiThreadedConnManager());
client.setCredentials(OwnCloudCredentialsFactory.newBearerCredentials("fakeToken")); client.setCredentials(OwnCloudCredentialsFactory.newBearerCredentials("user", "fakeToken"));
Uri webdavUri = client.getWebdavUri(); Uri webdavUri = client.getWebdavUri();
assertTrue("WebDAV URI does not point to the right entry point", assertTrue("WebDAV URI does not point to the right entry point",
webdavUri.getPath().endsWith(AccountUtils.WEBDAV_PATH_4_0)); webdavUri.getPath().endsWith(AccountUtils.WEBDAV_PATH_4_0));

View File

@ -33,8 +33,8 @@ import android.test.AndroidTestCase;
import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.SimpleFactoryManager; import com.owncloud.android.lib.common.SimpleFactoryManager;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.test_project.R; import com.owncloud.android.lib.test_project.R;
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;

View File

@ -33,8 +33,8 @@ import android.test.AndroidTestCase;
import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.SingleSessionManager; import com.owncloud.android.lib.common.SingleSessionManager;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.test_project.R; import com.owncloud.android.lib.test_project.R;
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;

View File

@ -40,7 +40,7 @@ import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;

View File

@ -41,7 +41,7 @@ import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;