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

apply codestyle everywhere

This commit is contained in:
Hannes Achleitner 2018-12-18 08:27:26 +01:00
parent 6d05856fb7
commit 40690df5fa
102 changed files with 2415 additions and 2472 deletions

View File

@ -22,11 +22,11 @@
THE SOFTWARE. THE SOFTWARE.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest package="com.owncloud.android.lib"
package="com.owncloud.android.lib" xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0" > android:versionName="1.0">
<!-- USE_CREDENTIALS, MANAGE_ACCOUNTS and AUTHENTICATE_ACCOUNTS are needed for API < 23. <!-- USE_CREDENTIALS, MANAGE_ACCOUNTS and AUTHENTICATE_ACCOUNTS are needed for API < 23.
In API >= 23 the do not exist anymore --> In API >= 23 the do not exist anymore -->

View File

@ -11,7 +11,7 @@ import java.io.IOException;
/** /**
* Dynamic implementation of {@link OwnCloudClientManager}. * Dynamic implementation of {@link OwnCloudClientManager}.
* * <p>
* Wraps instances of {@link SingleSessionManager} and {@link SimpleFactoryManager} and delegates on one * Wraps instances of {@link SingleSessionManager} and {@link SimpleFactoryManager} and delegates on one
* or the other depending on the known version of the server corresponding to the {@link OwnCloudAccount} * or the other depending on the known version of the server corresponding to the {@link OwnCloudAccount}
* *
@ -26,17 +26,17 @@ public class DynamicSessionManager implements OwnCloudClientManager {
@Override @Override
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
throws AccountUtils.AccountNotFoundException, throws AccountUtils.AccountNotFoundException,
OperationCanceledException, AuthenticatorException, IOException { OperationCanceledException, AuthenticatorException, IOException {
OwnCloudVersion ownCloudVersion = null; OwnCloudVersion ownCloudVersion = null;
if (account.getSavedAccount() != null) { if (account.getSavedAccount() != null) {
ownCloudVersion = AccountUtils.getServerVersionForAccount( ownCloudVersion = AccountUtils.getServerVersionForAccount(
account.getSavedAccount(), context account.getSavedAccount(), context
); );
} }
if (ownCloudVersion != null && ownCloudVersion.isSessionMonitoringSupported()) { if (ownCloudVersion != null && ownCloudVersion.isSessionMonitoringSupported()) {
return mSingleSessionManager.getClientFor(account, context); return mSingleSessionManager.getClientFor(account, context);
} else { } else {
return mSimpleFactoryManager.getClientFor(account, context); return mSimpleFactoryManager.getClientFor(account, context);

View File

@ -24,14 +24,6 @@
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common;
import java.io.IOException;
import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AuthenticatorException; import android.accounts.AuthenticatorException;
@ -39,27 +31,33 @@ 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.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import java.io.IOException;
/** /**
* OwnCloud Account * OwnCloud Account
* *
* @author David A. Velasco * @author David A. Velasco
*/ */
public class OwnCloudAccount { public class OwnCloudAccount {
private Uri mBaseUri; private Uri mBaseUri;
private OwnCloudCredentials mCredentials; private OwnCloudCredentials mCredentials;
private String mDisplayName; private String mDisplayName;
private String mSavedAccountName; private String mSavedAccountName;
private Account mSavedAccount; private Account mSavedAccount;
/** /**
* Constructor for already saved OC accounts. * Constructor for already saved OC accounts.
* * <p>
* Do not use for anonymous credentials. * Do not use for anonymous credentials.
*/ */
public OwnCloudAccount(Account savedAccount, Context context) throws AccountNotFoundException { public OwnCloudAccount(Account savedAccount, Context context) throws AccountNotFoundException {
@ -77,19 +75,18 @@ public class OwnCloudAccount {
AccountManager ama = AccountManager.get(context.getApplicationContext()); AccountManager ama = AccountManager.get(context.getApplicationContext());
String baseUrl = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_OC_BASE_URL); String baseUrl = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_OC_BASE_URL);
if (baseUrl == null ) { if (baseUrl == null) {
throw new AccountNotFoundException(mSavedAccount, "Account not found", null); throw new AccountNotFoundException(mSavedAccount, "Account not found", null);
} }
mBaseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(context, mSavedAccount)); mBaseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(context, mSavedAccount));
mDisplayName = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_DISPLAY_NAME); mDisplayName = ama.getUserData(mSavedAccount, AccountUtils.Constants.KEY_DISPLAY_NAME);
} }
/** /**
* Constructor for non yet saved OC accounts. * Constructor for non yet saved OC accounts.
* *
* @param baseUri URI to the OC server to get access to. * @param baseUri URI to the OC server to get access to.
* @param credentials Credentials to authenticate in the server. NULL is valid for anonymous credentials. * @param credentials Credentials to authenticate in the server. NULL is valid for anonymous credentials.
*/ */
public OwnCloudAccount(Uri baseUri, OwnCloudCredentials credentials) { public OwnCloudAccount(Uri baseUri, OwnCloudCredentials credentials) {
if (baseUri == null) { if (baseUri == null) {
@ -99,14 +96,13 @@ public class OwnCloudAccount {
mSavedAccountName = null; mSavedAccountName = null;
mBaseUri = baseUri; mBaseUri = baseUri;
mCredentials = credentials != null ? mCredentials = credentials != null ?
credentials : OwnCloudCredentialsFactory.getAnonymousCredentials(); credentials : OwnCloudCredentialsFactory.getAnonymousCredentials();
String username = mCredentials.getUsername(); String username = mCredentials.getUsername();
if (username != null) { if (username != null) {
mSavedAccountName = AccountUtils.buildAccountName(mBaseUri, username); mSavedAccountName = AccountUtils.buildAccountName(mBaseUri, username);
} }
} }
/** /**
* Method for deferred load of account attributes from AccountManager * Method for deferred load of account attributes from AccountManager
* *
@ -131,13 +127,13 @@ public class OwnCloudAccount {
public Uri getBaseUri() { public Uri getBaseUri() {
return mBaseUri; return mBaseUri;
} }
public OwnCloudCredentials getCredentials() { public OwnCloudCredentials getCredentials() {
return mCredentials; return mCredentials;
} }
public String getName() { public String getName() {
return mSavedAccountName; return mSavedAccountName;
} }
public Account getSavedAccount() { public Account getSavedAccount() {

View File

@ -29,6 +29,7 @@ import android.accounts.AccountManager;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import android.net.Uri; import android.net.Uri;
import at.bitfire.dav4android.exception.HttpException;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
@ -40,16 +41,14 @@ import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.common.utils.RandomUtils; import com.owncloud.android.lib.common.utils.RandomUtils;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import okhttp3.Cookie;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import at.bitfire.dav4android.exception.HttpException;
import okhttp3.Cookie;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import static com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID; import static com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID;
public class OwnCloudClient extends HttpClient { public class OwnCloudClient extends HttpClient {
@ -94,15 +93,6 @@ public class OwnCloudClient extends HttpClient {
clearCookies(); clearCookies();
} }
public void setCredentials(OwnCloudCredentials credentials) {
if (credentials != null) {
mCredentials = credentials;
mCredentials.applyTo(this);
} else {
clearCredentials();
}
}
public void clearCredentials() { public void clearCredentials() {
if (!(mCredentials instanceof OwnCloudAnonymousCredentials)) { if (!(mCredentials instanceof OwnCloudAnonymousCredentials)) {
mCredentials = OwnCloudCredentialsFactory.getAnonymousCredentials(); mCredentials = OwnCloudCredentialsFactory.getAnonymousCredentials();
@ -114,7 +104,7 @@ public class OwnCloudClient extends HttpClient {
mCredentials.applyTo(this); mCredentials.applyTo(this);
} }
public int executeHttpMethod (HttpBaseMethod method) throws Exception { public int executeHttpMethod(HttpBaseMethod method) throws Exception {
boolean repeatWithFreshCredentials; boolean repeatWithFreshCredentials;
int repeatCounter = 0; int repeatCounter = 0;
int status; int status;
@ -125,7 +115,7 @@ public class OwnCloudClient extends HttpClient {
status = method.execute(); status = method.execute();
checkFirstRedirection(method); checkFirstRedirection(method);
if(mFollowRedirects && !isIdPRedirection()) { if (mFollowRedirects && !isIdPRedirection()) {
status = followRedirection(method).getLastStatus(); status = followRedirection(method).getLastStatus();
} }
@ -140,12 +130,12 @@ public class OwnCloudClient extends HttpClient {
private void checkFirstRedirection(HttpBaseMethod method) { private void checkFirstRedirection(HttpBaseMethod method) {
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER); final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
if(location != null && !location.isEmpty()) { if (location != null && !location.isEmpty()) {
mRedirectedLocation = location; mRedirectedLocation = location;
} }
} }
private int executeRedirectedHttpMethod (HttpBaseMethod method) throws Exception { private int executeRedirectedHttpMethod(HttpBaseMethod method) throws Exception {
boolean repeatWithFreshCredentials; boolean repeatWithFreshCredentials;
int repeatCounter = 0; int repeatCounter = 0;
int status; int status;
@ -217,9 +207,9 @@ public class OwnCloudClient extends HttpClient {
try { try {
status = executeRedirectedHttpMethod(method); status = executeRedirectedHttpMethod(method);
} catch (HttpException e) { } catch (HttpException e) {
if(e.getMessage().contains(Integer.toString(HttpConstants.HTTP_MOVED_TEMPORARILY))) { if (e.getMessage().contains(Integer.toString(HttpConstants.HTTP_MOVED_TEMPORARILY))) {
status = HttpConstants.HTTP_MOVED_TEMPORARILY; status = HttpConstants.HTTP_MOVED_TEMPORARILY;
} else { } else {
throw e; throw e;
} }
} }
@ -242,7 +232,9 @@ public class OwnCloudClient extends HttpClient {
public void exhaustResponse(InputStream responseBodyAsStream) { public void exhaustResponse(InputStream responseBodyAsStream) {
if (responseBodyAsStream != null) { if (responseBodyAsStream != null) {
try { try {
while (responseBodyAsStream.read(sExhaustBuffer) >= 0) ; while (responseBodyAsStream.read(sExhaustBuffer) >= 0) {
;
}
responseBodyAsStream.close(); responseBodyAsStream.close();
} catch (IOException io) { } catch (IOException io) {
@ -252,7 +244,7 @@ public class OwnCloudClient extends HttpClient {
} }
} }
public Uri getBaseFilesWebDavUri(){ public Uri getBaseFilesWebDavUri() {
return Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0); return Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0);
} }
@ -260,7 +252,7 @@ public class OwnCloudClient extends HttpClient {
return mCredentials instanceof OwnCloudAnonymousCredentials return mCredentials instanceof OwnCloudAnonymousCredentials
? Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0) ? Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0)
: Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId( : Uri.parse(mBaseUri + WEBDAV_FILES_PATH_4_0 + AccountUtils.getUserId(
mAccount.getSavedAccount(), getContext() mAccount.getSavedAccount(), getContext()
) )
); );
} }
@ -269,14 +261,18 @@ public class OwnCloudClient extends HttpClient {
return mCredentials instanceof OwnCloudAnonymousCredentials return mCredentials instanceof OwnCloudAnonymousCredentials
? Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0) ? Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0)
: Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0 + AccountUtils.getUserId( : Uri.parse(mBaseUri + WEBDAV_UPLOADS_PATH_4_0 + AccountUtils.getUserId(
mAccount.getSavedAccount(), getContext() mAccount.getSavedAccount(), getContext()
) )
); );
} }
public Uri getBaseUri() {
return mBaseUri;
}
/** /**
* Sets the root URI to the ownCloud server. * Sets the root URI to the ownCloud server.
* * <p>
* Use with care. * Use with care.
* *
* @param uri * @param uri
@ -288,14 +284,19 @@ public class OwnCloudClient extends HttpClient {
mBaseUri = uri; mBaseUri = uri;
} }
public Uri getBaseUri() {
return mBaseUri;
}
public final OwnCloudCredentials getCredentials() { public final OwnCloudCredentials getCredentials() {
return mCredentials; return mCredentials;
} }
public void setCredentials(OwnCloudCredentials credentials) {
if (credentials != null) {
mCredentials = credentials;
mCredentials.applyTo(this);
} else {
clearCredentials();
}
}
private void logCookie(Cookie cookie) { private void logCookie(Cookie cookie) {
Log_OC.d(TAG, "Cookie name: " + cookie.name()); Log_OC.d(TAG, "Cookie name: " + cookie.name());
Log_OC.d(TAG, " value: " + cookie.value()); Log_OC.d(TAG, " value: " + cookie.value());
@ -348,27 +349,27 @@ public class OwnCloudClient extends HttpClient {
); );
} }
public void setOwnCloudVersion(OwnCloudVersion version) {
mVersion = version;
}
public OwnCloudVersion getOwnCloudVersion() { public OwnCloudVersion getOwnCloudVersion() {
return mVersion; return mVersion;
} }
public void setAccount(OwnCloudAccount account) { public void setOwnCloudVersion(OwnCloudVersion version) {
this.mAccount = account; mVersion = version;
} }
public OwnCloudAccount getAccount() { public OwnCloudAccount getAccount() {
return mAccount; return mAccount;
} }
public void setAccount(OwnCloudAccount account) {
this.mAccount = account;
}
/** /**
* Checks the status code of an execution and decides if should be repeated with fresh credentials. * Checks the status code of an execution and decides if should be repeated with fresh credentials.
* * <p>
* Invalidates current credentials if the request failed as anauthorized. * Invalidates current credentials if the request failed as anauthorized.
* * <p>
* Refresh current credentials if possible, and marks a retry. * Refresh current credentials if possible, and marks a retry.
* *
* @param status * @param status
@ -416,10 +417,9 @@ public class OwnCloudClient extends HttpClient {
* Determines if credentials should be invalidated according the to the HTTPS status * Determines if credentials should be invalidated according the to the HTTPS status
* of a network request just performed. * of a network request just performed.
* *
* @param httpStatusCode Result of the last request ran with the 'credentials' belows. * @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
* @return 'True' if credentials should and might be invalidated, 'false' if shouldn't or * cannot be invalidated with the given arguments.
* cannot be invalidated with the given arguments.
*/ */
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) { private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
@ -437,10 +437,10 @@ public class OwnCloudClient extends HttpClient {
/** /**
* Invalidates credentials stored for the given account in the system {@link AccountManager} and in * Invalidates credentials stored for the given account in the system {@link AccountManager} and in
* current {@link OwnCloudClientManagerFactory#getDefaultSingleton()} instance. * current {@link OwnCloudClientManagerFactory#getDefaultSingleton()} instance.
* * <p>
* {@link #shouldInvalidateAccountCredentials(int)} should be called first. * {@link #shouldInvalidateAccountCredentials(int)} should be called first.
* *
* @return 'True' if invalidation was successful, 'false' otherwise. * @return 'True' if invalidation was successful, 'false' otherwise.
*/ */
private boolean invalidateAccountCredentials() { private boolean invalidateAccountCredentials() {
AccountManager am = AccountManager.get(getContext()); AccountManager am = AccountManager.get(getContext());
@ -462,6 +462,7 @@ public class OwnCloudClient extends HttpClient {
/** /**
* Check if the redirection is to an identity provider such as SAML or wayf * 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 * @return true if the redirection location includes SAML or wayf, false otherwise
*/ */
private boolean isIdPRedirection() { private boolean isIdPRedirection() {

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -43,29 +43,28 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import java.io.IOException; import java.io.IOException;
public class OwnCloudClientFactory { public class OwnCloudClientFactory {
final private static String TAG = OwnCloudClientFactory.class.getSimpleName(); final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
/** /**
* Creates a OwnCloudClient setup for an ownCloud account * Creates a OwnCloudClient setup for an ownCloud account
* * <p>
* 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} * @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.
* @throws OperationCanceledException If the authenticator operation was cancelled while * @throws OperationCanceledException If the authenticator operation was cancelled while
* getting the authorization token for the account. * getting the authorization token for the account.
* @throws IOException If there was some I/O error while getting the * @throws IOException If there was some I/O error while getting the
* 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
*
*/ */
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,
AccountNotFoundException { AccountNotFoundException {
Uri baseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(appContext, account)); Uri baseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(appContext, account));
@ -79,57 +78,60 @@ public class OwnCloudClientFactory {
String username = AccountUtils.getUsernameForAccount(account); String username = AccountUtils.getUsernameForAccount(account);
if (isOauth2) { // TODO avoid a call to getUserData here if (isOauth2) { // TODO avoid a call to getUserData here
AccountManagerFuture<Bundle> future = am.getAuthToken( AccountManagerFuture<Bundle> future = am.getAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
null, null,
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(username, 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
AccountManagerFuture<Bundle> future = am.getAuthToken( AccountManagerFuture<Bundle> future = am.getAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
null, null,
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.newSamlSsoCredentials(username, accessToken) OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken)
); );
} else { } else {
AccountManagerFuture<Bundle> future = am.getAuthToken( AccountManagerFuture<Bundle> future = am.getAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypePass(account.type), AccountTypeUtils.getAuthTokenTypePass(account.type),
null, null,
currentActivity, currentActivity,
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);
client.setCredentials( client.setCredentials(
OwnCloudCredentialsFactory.newBasicCredentials( OwnCloudCredentialsFactory.newBasicCredentials(
username, username,
password, password,
(version != null && version.isPreemptiveAuthenticationPreferred()) (version != null && version.isPreemptiveAuthenticationPreferred())
) )
); );
} }
@ -142,10 +144,10 @@ public class OwnCloudClientFactory {
/** /**
* 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.
* *
* @param uri URL to the ownCloud server; BASE ENTRY POINT, not WebDavPATH * @param uri URL to the ownCloud server; BASE ENTRY POINT, not WebDavPATH
* @param context Android context where the OwnCloudClient is being created. * @param context Android context where the OwnCloudClient is being created.
* @return A OwnCloudClient object ready to be used * @return A OwnCloudClient object ready to be used
*/ */
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context, public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
boolean followRedirects) { boolean followRedirects) {
@ -154,7 +156,7 @@ public class OwnCloudClientFactory {
client.setFollowRedirects(followRedirects); client.setFollowRedirects(followRedirects);
client.setContext(context); client.setContext(context);
return client; return client;
} }
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,17 +24,17 @@
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common;
import java.io.IOException;
import android.accounts.AuthenticatorException; import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException; import android.accounts.OperationCanceledException;
import android.content.Context; import android.content.Context;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import java.io.IOException;
/** /**
* Manager to create and reuse OwnCloudClient instances to access remote OC servers. * Manager to create and reuse OwnCloudClient instances to access remote OC servers.
* *
* @author David A. Velasco * @author David A. Velasco
* @author masensio * @author masensio
* @author Christian Schabesberger * @author Christian Schabesberger
@ -42,13 +42,13 @@ import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundExce
public interface OwnCloudClientManager { public interface OwnCloudClientManager {
OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException, OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException,
OperationCanceledException, AuthenticatorException, OperationCanceledException, AuthenticatorException,
IOException; IOException;
OwnCloudClient removeClientFor(OwnCloudAccount account); OwnCloudClient removeClientFor(OwnCloudAccount account);
void saveAllClients(Context context, String accountType) void saveAllClients(Context context, String accountType)
throws AccountNotFoundException, AuthenticatorException, throws AccountNotFoundException, AuthenticatorException,
IOException, OperationCanceledException; IOException, OperationCanceledException;
} }

View File

@ -25,16 +25,8 @@ package com.owncloud.android.lib.common;
public class OwnCloudClientManagerFactory { public class OwnCloudClientManagerFactory {
public static enum Policy {
ALWAYS_NEW_CLIENT,
SINGLE_SESSION_PER_ACCOUNT,
SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING
}
private static Policy sDefaultPolicy = Policy.ALWAYS_NEW_CLIENT; private static Policy sDefaultPolicy = Policy.ALWAYS_NEW_CLIENT;
private static OwnCloudClientManager sDefaultSingleton; private static OwnCloudClientManager sDefaultSingleton;
private static String sUserAgent; private static String sUserAgent;
public static OwnCloudClientManager newDefaultOwnCloudClientManager() { public static OwnCloudClientManager newDefaultOwnCloudClientManager() {
@ -78,26 +70,32 @@ public class OwnCloudClientManagerFactory {
sDefaultPolicy = policy; sDefaultPolicy = policy;
} }
public static void setUserAgent(String userAgent) {
sUserAgent = userAgent;
}
public static String getUserAgent() { public static String getUserAgent() {
return sUserAgent; return sUserAgent;
} }
public static void setUserAgent(String userAgent) {
sUserAgent = userAgent;
}
private static boolean defaultSingletonMustBeUpdated(Policy policy) { private static boolean defaultSingletonMustBeUpdated(Policy policy) {
if (sDefaultSingleton == null) { if (sDefaultSingleton == null) {
return false; return false;
} }
if (policy == Policy.ALWAYS_NEW_CLIENT && if (policy == Policy.ALWAYS_NEW_CLIENT &&
!(sDefaultSingleton instanceof SimpleFactoryManager)) { !(sDefaultSingleton instanceof SimpleFactoryManager)) {
return true; return true;
} }
if (policy == Policy.SINGLE_SESSION_PER_ACCOUNT && if (policy == Policy.SINGLE_SESSION_PER_ACCOUNT &&
!(sDefaultSingleton instanceof SingleSessionManager)) { !(sDefaultSingleton instanceof SingleSessionManager)) {
return true; return true;
} }
return false; return false;
} }
public static enum Policy {
ALWAYS_NEW_CLIENT,
SINGLE_SESSION_PER_ACCOUNT,
SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING
}
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,13 +24,11 @@
package com.owncloud.android.lib.common; package com.owncloud.android.lib.common;
import android.accounts.AuthenticatorException; import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException; import android.accounts.OperationCanceledException;
import android.content.Context; import android.content.Context;
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.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import java.io.IOException; import java.io.IOException;
@ -46,16 +44,16 @@ public class SimpleFactoryManager implements OwnCloudClientManager {
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : "); Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(
account.getBaseUri(), account.getBaseUri(),
context.getApplicationContext(), context.getApplicationContext(),
true); true);
Log_OC.v(TAG, " new client {" + Log_OC.v(TAG, " new client {" +
(account.getName() != null ? (account.getName() != null ?
account.getName() : account.getName() :
AccountUtils.buildAccountName(account.getBaseUri(), "") AccountUtils.buildAccountName(account.getBaseUri(), "")
) + ", " + client.hashCode() + "}"); ) + ", " + client.hashCode() + "}");
if (account.getCredentials() == null) { if (account.getCredentials() == null) {
account.loadCredentials(context); account.loadCredentials(context);

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -43,7 +43,7 @@ import java.util.concurrent.ConcurrentMap;
/** /**
* Implementation of {@link OwnCloudClientManager} * Implementation of {@link OwnCloudClientManager}
* * <p>
* TODO check multithreading safety * TODO check multithreading safety
* *
* @author David A. Velasco * @author David A. Velasco
@ -57,11 +57,10 @@ public class SingleSessionManager implements OwnCloudClientManager {
private static final String TAG = SingleSessionManager.class.getSimpleName(); private static final String TAG = SingleSessionManager.class.getSimpleName();
private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername = private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername = private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
@Override @Override
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException, public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
@ -77,9 +76,9 @@ public class SingleSessionManager implements OwnCloudClientManager {
OwnCloudClient client = null; OwnCloudClient client = null;
String accountName = account.getName(); String accountName = account.getName();
String sessionName = account.getCredentials() == null ? "" : String sessionName = account.getCredentials() == null ? "" :
AccountUtils.buildAccountName( AccountUtils.buildAccountName(
account.getBaseUri(), account.getBaseUri(),
account.getCredentials().getAuthToken()); account.getCredentials().getAuthToken());
if (accountName != null) { if (accountName != null) {
client = mClientsWithKnownUsername.get(accountName); client = mClientsWithKnownUsername.get(accountName);
@ -110,9 +109,9 @@ public class SingleSessionManager implements OwnCloudClientManager {
if (client == null) { if (client == null) {
// no client to reuse - create a new one // no client to reuse - create a new one
client = OwnCloudClientFactory.createOwnCloudClient( client = OwnCloudClientFactory.createOwnCloudClient(
account.getBaseUri(), account.getBaseUri(),
context.getApplicationContext(), context.getApplicationContext(),
true); // TODO remove dependency on OwnCloudClientFactory true); // TODO remove dependency on OwnCloudClientFactory
client.setAccount(account); client.setAccount(account);
client.setContext(context); client.setContext(context);
client.setOwnCloudClientManager(this); client.setOwnCloudClientManager(this);
@ -152,7 +151,6 @@ public class SingleSessionManager implements OwnCloudClientManager {
return client; return client;
} }
@Override @Override
public OwnCloudClient removeClientFor(OwnCloudAccount account) { public OwnCloudClient removeClientFor(OwnCloudAccount account) {
if (Log.isLoggable(TAG, Log.DEBUG)) { if (Log.isLoggable(TAG, Log.DEBUG)) {
@ -187,7 +185,6 @@ public class SingleSessionManager implements OwnCloudClientManager {
return null; return null;
} }
@Override @Override
public void saveAllClients(Context context, String accountType) { public void saveAllClients(Context context, String accountType) {
@ -202,9 +199,9 @@ public class SingleSessionManager implements OwnCloudClientManager {
accountName = accountNames.next(); accountName = accountNames.next();
account = new Account(accountName, accountType); account = new Account(accountName, accountType);
AccountUtils.saveClient( AccountUtils.saveClient(
mClientsWithKnownUsername.get(accountName), mClientsWithKnownUsername.get(accountName),
account, account,
context); context);
} }
if (Log.isLoggable(TAG, Log.DEBUG)) { if (Log.isLoggable(TAG, Log.DEBUG)) {

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -33,17 +33,17 @@ public class AccountTypeUtils {
public static String getAuthTokenTypePass(String accountType) { public static String getAuthTokenTypePass(String accountType) {
return accountType + ".password"; return accountType + ".password";
} }
public static String getAuthTokenTypeAccessToken(String accountType) { public static String getAuthTokenTypeAccessToken(String accountType) {
return accountType + ".oauth2.access_token"; return accountType + ".oauth2.access_token";
} }
public static String getAuthTokenTypeRefreshToken(String accountType) { public static String getAuthTokenTypeRefreshToken(String accountType) {
return accountType + ".oauth2.refresh_token"; return accountType + ".oauth2.refresh_token";
} }
public static String getAuthTokenTypeSamlSessionCookie(String accountType) { public static String getAuthTokenTypeSamlSessionCookie(String accountType) {
return accountType + ".saml.web_sso.session_cookie"; return accountType + ".saml.web_sso.session_cookie";
} }
} }

View File

@ -1,23 +1,23 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -39,13 +39,12 @@ 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.files.FileUtils; import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import okhttp3.Cookie;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import okhttp3.Cookie;
public class AccountUtils { public class AccountUtils {
private static final String TAG = AccountUtils.class.getSimpleName(); private static final String TAG = AccountUtils.class.getSimpleName();
@ -53,13 +52,13 @@ 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 Valid Android {@link Context}, needed to access the {@link AccountManager} * @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
* @param account A stored ownCloud {@link Account} * @param account A stored ownCloud {@link Account}
* @return Full URL to WebDAV endpoint in the server corresponding to 'account'. * @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
*/ */
public static String getWebDavUrlForAccount(Context context, Account account) public static String getWebDavUrlForAccount(Context context, Account account)
throws AccountNotFoundException { throws AccountNotFoundException {
String webDavUrlForAccount = ""; String webDavUrlForAccount = "";
try { try {
@ -80,19 +79,20 @@ public class AccountUtils {
/** /**
* Extracts url server from the account * Extracts url server from the account
* *
* @param context Valid Android {@link Context}, needed to access the {@link AccountManager} * @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
* @param account A stored ownCloud {@link Account} * @param account A stored ownCloud {@link Account}
* @return Full URL to the server corresponding to 'account', ending in the base path * @return Full URL to the server corresponding to 'account', ending in the base path
* common to all API endpoints. * 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)
throws AccountNotFoundException { throws AccountNotFoundException {
AccountManager ama = AccountManager.get(context.getApplicationContext()); AccountManager ama = AccountManager.get(context.getApplicationContext());
String baseurl = ama.getUserData(account, Constants.KEY_OC_BASE_URL); String baseurl = ama.getUserData(account, Constants.KEY_OC_BASE_URL);
if (baseurl == null) if (baseurl == null) {
throw new AccountNotFoundException(account, "Account not found", null); throw new AccountNotFoundException(account, "Account not found", null);
}
return baseurl; return baseurl;
} }
@ -116,8 +116,8 @@ public class AccountUtils {
/** /**
* Get the stored server version corresponding to an OC account. * Get the stored server version corresponding to an OC account.
* *
* @param account An OC account * @param account An OC account
* @param context Application context * @param context Application context
* @return Version of the OC server, according to last check * @return Version of the OC server, according to last check
*/ */
public static OwnCloudVersion getServerVersionForAccount(Account account, Context context) { public static OwnCloudVersion getServerVersionForAccount(Account account, Context context) {
@ -140,7 +140,7 @@ public class AccountUtils {
* @throws OperationCanceledException * @throws OperationCanceledException
*/ */
public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account) public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account)
throws OperationCanceledException, AuthenticatorException, IOException { throws OperationCanceledException, AuthenticatorException, IOException {
OwnCloudCredentials credentials; OwnCloudCredentials credentials;
AccountManager am = AccountManager.get(context); AccountManager am = AccountManager.get(context);
@ -158,30 +158,30 @@ public class AccountUtils {
if (isOauth2) { if (isOauth2) {
String accessToken = am.blockingGetAuthToken( String accessToken = am.blockingGetAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
false); false);
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken); credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
} else if (isSamlSso) { } else if (isSamlSso) {
String accessToken = am.blockingGetAuthToken( String accessToken = am.blockingGetAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
false); false);
credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken); credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken);
} else { } else {
String password = am.blockingGetAuthToken( String password = am.blockingGetAuthToken(
account, account,
AccountTypeUtils.getAuthTokenTypePass(account.type), AccountTypeUtils.getAuthTokenTypePass(account.type),
false); false);
credentials = OwnCloudCredentialsFactory.newBasicCredentials( credentials = OwnCloudCredentialsFactory.newBasicCredentials(
username, username,
password, password,
version.isPreemptiveAuthenticationPreferred() version.isPreemptiveAuthenticationPreferred()
); );
} }
@ -190,8 +190,9 @@ public class AccountUtils {
/** /**
* Get the user id corresponding to an OC account. * Get the user id corresponding to an OC account.
*
* @param account ownCloud account * @param account ownCloud account
* @return user id * @return user id
*/ */
public static String getUserId(Account account, Context context) { public static String getUserId(Account account, Context context) {
AccountManager accountMgr = AccountManager.get(context); AccountManager accountMgr = AccountManager.get(context);
@ -232,7 +233,7 @@ public class AccountUtils {
String cookiesString = client.getCookiesString(); String cookiesString = client.getCookiesString();
if (!"".equals(cookiesString)) { if (!"".equals(cookiesString)) {
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString); ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
Log_OC.d(TAG, "Saving Cookies: "+ cookiesString ); Log_OC.d(TAG, "Saving Cookies: " + cookiesString);
} }
} }
} }
@ -240,9 +241,9 @@ public class AccountUtils {
/** /**
* Restore the client cookies persisted in an account stored in the system AccountManager. * Restore the client cookies persisted in an account stored in the system AccountManager.
* *
* @param account Stored account. * @param account Stored account.
* @param client Client to restore cookies in. * @param client Client to restore cookies in.
* @param context Android context used to access the system AccountManager. * @param context Android context used to access the system AccountManager.
*/ */
public static void restoreCookies(Account account, OwnCloudClient client, Context context) { public static void restoreCookies(Account account, OwnCloudClient client, Context context) {
if (account == null) { if (account == null) {
@ -260,10 +261,12 @@ public class AccountUtils {
if (cookiesString != null) { if (cookiesString != null) {
String[] rawCookies = cookiesString.split(";"); String[] rawCookies = cookiesString.split(";");
List<Cookie> cookieList = new ArrayList<>(rawCookies.length); List<Cookie> cookieList = new ArrayList<>(rawCookies.length);
for(String rawCookie : rawCookies) { for (String rawCookie : rawCookies) {
rawCookie = rawCookie.replace(" ", ""); rawCookie = rawCookie.replace(" ", "");
final int equalPos = rawCookie.indexOf('='); final int equalPos = rawCookie.indexOf('=');
if (equalPos == -1) continue; if (equalPos == -1) {
continue;
}
cookieList.add(new Cookie.Builder() cookieList.add(new Cookie.Builder()
.name(rawCookie.substring(0, equalPos)) .name(rawCookie.substring(0, equalPos))
.value(rawCookie.substring(equalPos + 1)) .value(rawCookie.substring(equalPos + 1))

View File

@ -26,7 +26,6 @@ package com.owncloud.android.lib.common.authentication;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpClient; import com.owncloud.android.lib.common.http.HttpClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import okhttp3.Credentials; import okhttp3.Credentials;
public class OwnCloudBasicCredentials implements OwnCloudCredentials { public class OwnCloudBasicCredentials implements OwnCloudCredentials {

View File

@ -39,7 +39,7 @@ public class OwnCloudCredentialsFactory {
} }
public static OwnCloudCredentials newBasicCredentials( public static OwnCloudCredentials newBasicCredentials(
String username, String password, boolean preemptiveMode String username, String password, boolean preemptiveMode
) { ) {
return new OwnCloudBasicCredentials(username, password, preemptiveMode); return new OwnCloudBasicCredentials(username, password, preemptiveMode);
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -32,14 +32,13 @@ public class BearerCredentials {
public static final int HASH_SEED = 17; public static final int HASH_SEED = 17;
public static final int HASH_OFFSET = 37; public static final int HASH_OFFSET = 37;
private String mAccessToken; private String mAccessToken;
/** /**
* The constructor with the bearer token * The constructor with the bearer token
* *
* @param token The bearer token * @param token The bearer token
*/ */
public BearerCredentials(String token) { public BearerCredentials(String token) {
/*if (token == null) { /*if (token == null) {
@ -48,21 +47,19 @@ public class BearerCredentials {
mAccessToken = (token == null) ? "" : token; mAccessToken = (token == null) ? "" : token;
} }
/** /**
* Returns the access token * Returns the access token
* *
* @return The access token * @return The access token
*/ */
public String getAccessToken() { public String getAccessToken() {
return mAccessToken; return mAccessToken;
} }
/** /**
* Get this object string. * Get this object string.
* *
* @return The access token * @return The access token
*/ */
public String toString() { public String toString() {
return mAccessToken; return mAccessToken;
@ -74,19 +71,22 @@ public class BearerCredentials {
* @return The hash code of the access token * @return The hash code of the access token
*/ */
public int hashCode() { public int hashCode() {
return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode(); return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode();
} }
/** /**
* These credentials are assumed equal if accessToken is the same. * These credentials are assumed equal if accessToken is the same.
* *
* @param o The other object to compare with. * @param o The other object to compare with.
* * @return 'True' if the object is equivalent.
* @return 'True' if the object is equivalent.
*/ */
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == null) return false; if (o == null) {
if (this == o) return true; return false;
}
if (this == o) {
return true;
}
if (this.getClass().equals(o.getClass())) { if (this.getClass().equals(o.getClass())) {
BearerCredentials that = (BearerCredentials) o; BearerCredentials that = (BearerCredentials) o;
if (mAccessToken.equals(that.mAccessToken)) { if (mAccessToken.equals(that.mAccessToken)) {

View File

@ -26,34 +26,34 @@
package com.owncloud.android.lib.common.authentication.oauth; package com.owncloud.android.lib.common.authentication.oauth;
/** /**
* Constant values for OAuth 2 protocol. * Constant values for OAuth 2 protocol.
* * <p>
* Includes required and optional parameter NAMES used in the 'authorization code' grant type. * Includes required and optional parameter NAMES used in the 'authorization code' grant type.
*/ */
public class OAuth2Constants { public class OAuth2Constants {
/// Parameters to send to the Authorization Endpoint /// Parameters to send to the Authorization Endpoint
public static final String KEY_RESPONSE_TYPE = "response_type"; public static final String KEY_RESPONSE_TYPE = "response_type";
public static final String KEY_REDIRECT_URI = "redirect_uri"; public static final String KEY_REDIRECT_URI = "redirect_uri";
public static final String KEY_CLIENT_ID = "client_id"; public static final String KEY_CLIENT_ID = "client_id";
public static final String KEY_SCOPE = "scope"; public static final String KEY_SCOPE = "scope";
public static final String KEY_STATE = "state"; public static final String KEY_STATE = "state";
/// Additional parameters to send to the Token Endpoint /// Additional parameters to send to the Token Endpoint
public static final String KEY_GRANT_TYPE = "grant_type"; public static final String KEY_GRANT_TYPE = "grant_type";
public static final String KEY_CODE = "code"; public static final String KEY_CODE = "code";
// Used to get the Access Token using Refresh Token // Used to get the Access Token using Refresh Token
public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token"; public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
/// Parameters received in an OK response from the Token Endpoint /// Parameters received in an OK response from the Token Endpoint
public static final String KEY_ACCESS_TOKEN = "access_token"; public static final String KEY_ACCESS_TOKEN = "access_token";
public static final String KEY_TOKEN_TYPE = "token_type"; public static final String KEY_TOKEN_TYPE = "token_type";
public static final String KEY_EXPIRES_IN = "expires_in"; public static final String KEY_EXPIRES_IN = "expires_in";
public static final String KEY_REFRESH_TOKEN = "refresh_token"; public static final String KEY_REFRESH_TOKEN = "refresh_token";
/// Parameters in an ERROR response /// Parameters in an ERROR response
public static final String KEY_ERROR = "error"; public static final String KEY_ERROR = "error";
public static final String KEY_ERROR_DESCRIPTION = "error_description"; public static final String KEY_ERROR_DESCRIPTION = "error_description";

View File

@ -29,42 +29,37 @@ package com.owncloud.android.lib.common.authentication.oauth;
import android.net.Uri; 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.OwnCloudClient;
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod; import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import org.json.JSONObject; import org.json.JSONObject;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> { public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> {
private final String mAccessTokenEndpointPath;
private final OAuth2ResponseParser mResponseParser;
private String mGrantType; private String mGrantType;
private String mCode; private String mCode;
private String mClientId; private String mClientId;
private String mClientSecret; private String mClientSecret;
private String mRedirectUri; private String mRedirectUri;
private final String mAccessTokenEndpointPath;
private final OAuth2ResponseParser mResponseParser;
public OAuth2GetAccessTokenOperation( public OAuth2GetAccessTokenOperation(
String grantType, String grantType,
String code, String code,
String clientId, String clientId,
String secretId, String secretId,
String redirectUri, String redirectUri,
String accessTokenEndpointPath String accessTokenEndpointPath
) { ) {
mClientId = clientId; mClientId = clientId;
mClientSecret = secretId; mClientSecret = secretId;
@ -73,9 +68,9 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, S
mCode = code; mCode = code;
mAccessTokenEndpointPath = mAccessTokenEndpointPath =
accessTokenEndpointPath != null ? accessTokenEndpointPath != null ?
accessTokenEndpointPath : accessTokenEndpointPath :
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
; ;
mResponseParser = new OAuth2ResponseParser(); mResponseParser = new OAuth2ResponseParser();
@ -84,7 +79,7 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, S
@Override @Override
protected RemoteOperationResult run(OwnCloudClient client) { protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult<Map<String, String>> result = null; RemoteOperationResult<Map<String, String>> result = null;
try { try {
final RequestBody requestBody = new MultipartBody.Builder() final RequestBody requestBody = new MultipartBody.Builder()
@ -116,7 +111,7 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, S
if (response != null && response.length() > 0) { if (response != null && response.length() > 0) {
JSONObject tokenJson = new JSONObject(response); JSONObject tokenJson = new JSONObject(response);
Map<String, String> accessTokenResult = Map<String, String> accessTokenResult =
mResponseParser.parseAccessTokenResult(tokenJson); mResponseParser.parseAccessTokenResult(tokenJson);
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null || if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) { accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR); result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR);
@ -133,7 +128,7 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, S
} catch (Exception e) { } catch (Exception e) {
result = new RemoteOperationResult<>(e); result = new RemoteOperationResult<>(e);
} }
return result; return result;
} }

View File

@ -31,36 +31,35 @@ public interface OAuth2Provider {
/** /**
* {@link OAuth2RequestBuilder} implementation for this provider. * {@link OAuth2RequestBuilder} implementation for this provider.
* *
* @return {@link OAuth2RequestBuilder} implementation. * @return {@link OAuth2RequestBuilder} implementation.
*/ */
OAuth2RequestBuilder getOperationBuilder(); 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} * Configuration of the client that is using this {@link OAuth2Provider}
* return Configuration of the client that is usinng this {@link OAuth2Provider} * return Configuration of the client that is usinng this {@link OAuth2Provider}
*/ */
OAuth2ClientConfiguration getClientConfiguration(); OAuth2ClientConfiguration getClientConfiguration();
/** /**
* Set base URI to authorization server. * Set configuration of the client that will use this {@link OAuth2Provider}
* *
* @param authorizationServerUri Set base URL to authorization server. * @param oAuth2ClientConfiguration Configuration of the client that will use this {@link OAuth2Provider}
*/ */
void setAuthorizationServerUri(String authorizationServerUri); void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration);
/** /**
* base URI to authorization server. * base URI to authorization server.
* *
* @return Base URL to authorization server. * @return Base URL to authorization server.
*/ */
String getAuthorizationServerUri(); String getAuthorizationServerUri();
/**
* Set base URI to authorization server.
*
* @param authorizationServerUri Set base URL to authorization server.
*/
void setAuthorizationServerUri(String authorizationServerUri);
} }

View File

@ -26,7 +26,6 @@
package com.owncloud.android.lib.common.authentication.oauth; package com.owncloud.android.lib.common.authentication.oauth;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -36,20 +35,13 @@ public class OAuth2ProvidersRegistry {
private OAuth2Provider mDefaultProvider = null; private OAuth2Provider mDefaultProvider = null;
private OAuth2ProvidersRegistry () { 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. * Singleton accesor.
* *
* @return Singleton isntance of {@link OAuth2ProvidersRegistry} * @return Singleton isntance of {@link OAuth2ProvidersRegistry}
*/ */
public static OAuth2ProvidersRegistry getInstance() { public static OAuth2ProvidersRegistry getInstance() {
return LazyHolder.INSTANCE; return LazyHolder.INSTANCE;
@ -58,8 +50,8 @@ public class OAuth2ProvidersRegistry {
/** /**
* Register an {@link OAuth2Provider} with the name passed as parameter. * Register an {@link OAuth2Provider} with the name passed as parameter.
* *
* @param name Name to bind 'oAuthProvider' in the registry. * @param name Name to bind 'oAuthProvider' in the registry.
* @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry. * @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry.
* @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null. * @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null.
*/ */
public void registerProvider(String name, OAuth2Provider oAuth2Provider) { public void registerProvider(String name, OAuth2Provider oAuth2Provider) {
@ -89,7 +81,7 @@ public class OAuth2ProvidersRegistry {
/** /**
* Get default {@link OAuth2Provider}. * Get default {@link OAuth2Provider}.
* *
* @return Default provider, or NULL if there is no provider. * @return Default provider, or NULL if there is no provider.
*/ */
public OAuth2Provider getProvider() { public OAuth2Provider getProvider() {
return mDefaultProvider; return mDefaultProvider;
@ -98,8 +90,8 @@ public class OAuth2ProvidersRegistry {
/** /**
* Get {@link OAuth2Provider} registered with the name passed as parameter. * Get {@link OAuth2Provider} registered with the name passed as parameter.
* *
* @param name Name used to register the desired {@link OAuth2Provider} * @param name Name used to register the desired {@link OAuth2Provider}
* @return {@link OAuth2Provider} registered with the name 'name' * @return {@link OAuth2Provider} registered with the name 'name'
*/ */
public OAuth2Provider getProvider(String name) { public OAuth2Provider getProvider(String name) {
return mProviders.get(name); return mProviders.get(name);
@ -108,8 +100,8 @@ public class OAuth2ProvidersRegistry {
/** /**
* Sets the {@link OAuth2Provider} registered with the name passed as parameter as the default provider * 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. * @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'. * @return {@link OAuth2Provider} set as default, or NULL if no provider was registered with 'name'.
*/ */
public OAuth2Provider setDefaultProvider(String name) { public OAuth2Provider setDefaultProvider(String name) {
OAuth2Provider toDefault = mProviders.get(name); OAuth2Provider toDefault = mProviders.get(name);
@ -119,4 +111,11 @@ public class OAuth2ProvidersRegistry {
return toDefault; return toDefault;
} }
/**
* See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
*/
private static class LazyHolder {
private static final OAuth2ProvidersRegistry INSTANCE = new OAuth2ProvidersRegistry();
}
} }

View File

@ -31,7 +31,6 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class OAuth2QueryParser { public class OAuth2QueryParser {
private static final String TAG = OAuth2QueryParser.class.getName(); private static final String TAG = OAuth2QueryParser.class.getName();

View File

@ -1,59 +1,52 @@
/** /**
* ownCloud Android client application * ownCloud Android client application
*
* @author David González Verdugo
* @author Christian Schabesberger
*
* Copyright (C) 2018 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* @author David González Verdugo
* @author Christian Schabesberger
* <p>
* Copyright (C) 2018 ownCloud GmbH.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.owncloud.android.lib.common.authentication.oauth; package com.owncloud.android.lib.common.authentication.oauth;
import android.net.Uri; 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.OwnCloudClient;
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import org.json.JSONObject; import org.json.JSONObject;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> { public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> {
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName(); private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
private final String mAccessTokenEndpointPath;
private final OAuth2ResponseParser mResponseParser;
private String mClientId; private String mClientId;
private String mClientSecret; private String mClientSecret;
private String mRefreshToken; private String mRefreshToken;
private final String mAccessTokenEndpointPath;
private final OAuth2ResponseParser mResponseParser;
public OAuth2RefreshAccessTokenOperation( public OAuth2RefreshAccessTokenOperation(
String clientId, String clientId,
String secretId, String secretId,

View File

@ -30,10 +30,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
public interface OAuth2RequestBuilder { public interface OAuth2RequestBuilder {
enum OAuthRequest {
GET_AUTHORIZATION_CODE, CREATE_ACCESS_TOKEN, REFRESH_ACCESS_TOKEN
}
void setRequest(OAuthRequest operation); void setRequest(OAuthRequest operation);
void setGrantType(OAuth2GrantType grantType); void setGrantType(OAuth2GrantType grantType);
@ -45,4 +41,8 @@ public interface OAuth2RequestBuilder {
RemoteOperation buildOperation(); RemoteOperation buildOperation();
String buildUri(); String buildUri();
enum OAuthRequest {
GET_AUTHORIZATION_CODE, CREATE_ACCESS_TOKEN, REFRESH_ACCESS_TOKEN
}
} }

View File

@ -1,27 +1,25 @@
/** /**
* ownCloud Android client application * 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/>.
* *
* @author David A. Velasco
* <p>
* Copyright (C) 2017 ownCloud GmbH.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.owncloud.android.lib.common.authentication.oauth; package com.owncloud.android.lib.common.authentication.oauth;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -35,40 +33,40 @@ class OAuth2ResponseParser {
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) { if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.
getString(OAuth2Constants.KEY_ACCESS_TOKEN)); getString(OAuth2Constants.KEY_ACCESS_TOKEN));
} }
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) { if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.
getString(OAuth2Constants.KEY_TOKEN_TYPE)); getString(OAuth2Constants.KEY_TOKEN_TYPE));
} }
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) { if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.
getString(OAuth2Constants.KEY_EXPIRES_IN)); getString(OAuth2Constants.KEY_EXPIRES_IN));
} }
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) { if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.
getString(OAuth2Constants.KEY_REFRESH_TOKEN)); getString(OAuth2Constants.KEY_REFRESH_TOKEN));
} }
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) { if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.
getString(OAuth2Constants.KEY_SCOPE)); getString(OAuth2Constants.KEY_SCOPE));
} }
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) { if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.
getString(OAuth2Constants.KEY_ERROR)); getString(OAuth2Constants.KEY_ERROR));
} }
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) { if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.
getString(OAuth2Constants.KEY_ERROR_DESCRIPTION)); getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
} }
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) { if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.
getString(OAuth2Constants.KEY_ERROR_URI)); getString(OAuth2Constants.KEY_ERROR_URI));
} }
if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard
resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson. resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson.
getString(OAuth2Constants.KEY_USER_ID)); getString(OAuth2Constants.KEY_USER_ID));
} }
return resultTokenMap; return resultTokenMap;

View File

@ -46,19 +46,14 @@ public class OwnCloudOAuth2Provider implements OAuth2Provider {
return new OwnCloudOAuth2RequestBuilder(this); return new OwnCloudOAuth2RequestBuilder(this);
} }
@Override
public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
mClientConfiguration = oAuth2ClientConfiguration;
}
@Override @Override
public OAuth2ClientConfiguration getClientConfiguration() { public OAuth2ClientConfiguration getClientConfiguration() {
return mClientConfiguration; return mClientConfiguration;
} }
@Override @Override
public void setAuthorizationServerUri(String authorizationServerUri) { public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
mAuthorizationServerUrl = authorizationServerUri; mClientConfiguration = oAuth2ClientConfiguration;
} }
@Override @Override
@ -66,6 +61,11 @@ public class OwnCloudOAuth2Provider implements OAuth2Provider {
return mAuthorizationServerUrl; return mAuthorizationServerUrl;
} }
@Override
public void setAuthorizationServerUri(String authorizationServerUri) {
mAuthorizationServerUrl = authorizationServerUri;
}
public String getAccessTokenEndpointPath() { public String getAccessTokenEndpointPath() {
return mAccessTokenEndpointPath; return mAccessTokenEndpointPath;
} }

View File

@ -68,22 +68,22 @@ public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE && if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE &&
mGrantType != OAuth2GrantType.REFRESH_TOKEN) { mGrantType != OAuth2GrantType.REFRESH_TOKEN) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Unsupported grant type. Only " + "Unsupported grant type. Only " +
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " + OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " +
OAuth2GrantType.REFRESH_TOKEN + " are supported" OAuth2GrantType.REFRESH_TOKEN + " are supported"
); );
} }
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration(); OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
switch(mRequest) { switch (mRequest) {
case CREATE_ACCESS_TOKEN: case CREATE_ACCESS_TOKEN:
return new OAuth2GetAccessTokenOperation( return new OAuth2GetAccessTokenOperation(
mGrantType.getValue(), mGrantType.getValue(),
mCode, mCode,
clientConfiguration.getClientId(), clientConfiguration.getClientId(),
clientConfiguration.getClientSecret(), clientConfiguration.getClientSecret(),
clientConfiguration.getRedirectUri(), clientConfiguration.getRedirectUri(),
mOAuth2Provider.getAccessTokenEndpointPath() mOAuth2Provider.getAccessTokenEndpointPath()
); );
case REFRESH_ACCESS_TOKEN: case REFRESH_ACCESS_TOKEN:
@ -95,7 +95,7 @@ public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
); );
default: default:
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Unsupported request" "Unsupported request"
); );
} }
} }
@ -104,26 +104,26 @@ public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
public String buildUri() { public String buildUri() {
if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) { if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Unsupported grant type. Only " + "Unsupported grant type. Only " +
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider" OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider"
); );
} }
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration(); OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
Uri uri; Uri uri;
Uri.Builder uriBuilder; Uri.Builder uriBuilder;
switch(mRequest) { switch (mRequest) {
case GET_AUTHORIZATION_CODE: case GET_AUTHORIZATION_CODE:
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri()); uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
uriBuilder = uri.buildUpon(); uriBuilder = uri.buildUpon();
uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath()); uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath());
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
); );
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri() OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
); );
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId() OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
); );
uri = uriBuilder.build(); uri = uriBuilder.build();
@ -134,13 +134,13 @@ public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
uriBuilder = uri.buildUpon(); uriBuilder = uri.buildUpon();
uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath()); uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath());
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
); );
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri() OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
); );
uriBuilder.appendQueryParameter( uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId() OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
); );
uri = uriBuilder.build(); uri = uriBuilder.build();
@ -148,7 +148,7 @@ public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
default: default:
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Unsupported request" "Unsupported request"
); );
} }
} }

View File

@ -32,7 +32,15 @@ import com.owncloud.android.lib.common.http.interceptors.RequestHeaderIntercepto
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.network.NetworkUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -41,18 +49,9 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
/** /**
* Client used to perform network operations * Client used to perform network operations
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class HttpClient { public class HttpClient {
@ -63,21 +62,13 @@ public class HttpClient {
private static Context sContext; private static Context sContext;
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>(); private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
public static void setContext(Context context) {
sContext = context;
}
public Context getContext() {
return sContext;
}
public static OkHttpClient getOkHttpClient() { public static OkHttpClient getOkHttpClient() {
if (sOkHttpClient == null) { if (sOkHttpClient == null) {
try { try {
final X509TrustManager trustManager = new AdvancedX509TrustManager( final X509TrustManager trustManager = new AdvancedX509TrustManager(
NetworkUtils.getKnownServersStore(sContext)); NetworkUtils.getKnownServersStore(sContext));
final SSLContext sslContext = SSLContext.getInstance("TLS"); final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {trustManager}, null); sslContext.init(null, new TrustManager[]{trustManager}, null);
// Automatic cookie handling, NOT PERSISTENT // Automatic cookie handling, NOT PERSISTENT
CookieJar cookieJar = new CookieJar() { CookieJar cookieJar = new CookieJar() {
@ -109,8 +100,8 @@ public class HttpClient {
.sslSocketFactory(sslContext.getSocketFactory(), trustManager) .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
.hostnameVerifier((asdf, usdf) -> true) .hostnameVerifier((asdf, usdf) -> true)
.cookieJar(cookieJar); .cookieJar(cookieJar);
// TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok.
//.hostnameVerifier(new BrowserCompatHostnameVerifier()); //.hostnameVerifier(new BrowserCompatHostnameVerifier());
sOkHttpClient = clientBuilder.build(); sOkHttpClient = clientBuilder.build();
} catch (Exception e) { } catch (Exception e) {
@ -130,6 +121,31 @@ public class HttpClient {
return sOkHttpInterceptor; return sOkHttpInterceptor;
} }
/**
* Add header that will be included for all the requests from now on
*
* @param headerName
* @param headerValue
*/
public static void addHeaderForAllRequests(String headerName, String headerValue) {
getOkHttpInterceptor()
.addRequestInterceptor(
new RequestHeaderInterceptor(headerName, headerValue)
);
}
public static void deleteHeaderForAllRequests(String headerName) {
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
}
public Context getContext() {
return sContext;
}
public static void setContext(Context context) {
sContext = context;
}
public void disableAutomaticCookiesHandling() { public void disableAutomaticCookiesHandling() {
OkHttpClient.Builder clientBuilder = getOkHttpClient().newBuilder(); OkHttpClient.Builder clientBuilder = getOkHttpClient().newBuilder();
clientBuilder.cookieJar(new CookieJar() { clientBuilder.cookieJar(new CookieJar() {
@ -146,22 +162,6 @@ public class HttpClient {
sOkHttpClient = clientBuilder.build(); sOkHttpClient = clientBuilder.build();
} }
/**
* Add header that will be included for all the requests from now on
* @param headerName
* @param headerValue
*/
public static void addHeaderForAllRequests(String headerName, String headerValue) {
getOkHttpInterceptor()
.addRequestInterceptor(
new RequestHeaderInterceptor(headerName, headerValue)
);
}
public static void deleteHeaderForAllRequests(String headerName) {
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
}
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) { public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
return sCookieStore.get(httpUrl.host()); return sCookieStore.get(httpUrl.host());
} }

View File

@ -181,9 +181,13 @@ public class HttpConstants {
*************************************************** TIMEOUTS ********************************************** *************************************************** TIMEOUTS **********************************************
***********************************************************************************************************/ ***********************************************************************************************************/
/** Default timeout for waiting data from the server */ /**
* Default timeout for waiting data from the server
*/
public static final int DEFAULT_DATA_TIMEOUT = 60000; public static final int DEFAULT_DATA_TIMEOUT = 60000;
/** Default timeout for establishing a connection */ /**
* Default timeout for establishing a connection
*/
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000; public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
} }

View File

@ -24,16 +24,17 @@
package com.owncloud.android.lib.common.http.interceptors; package com.owncloud.android.lib.common.http.interceptors;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import okhttp3.Interceptor; import okhttp3.Interceptor;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
/** /**
* Http interceptor to use multiple interceptors in the same {@link okhttp3.OkHttpClient} instance * Http interceptor to use multiple interceptors in the same {@link okhttp3.OkHttpClient} instance
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class HttpInterceptor implements Interceptor { public class HttpInterceptor implements Interceptor {
@ -58,20 +59,12 @@ public class HttpInterceptor implements Interceptor {
return response; return response;
} }
public interface RequestInterceptor {
Request intercept(Request request) throws IOException;
}
public interface ResponseInterceptor {
Response intercept(Response response) throws IOException;
}
public HttpInterceptor addRequestInterceptor(RequestInterceptor requestInterceptor) { public HttpInterceptor addRequestInterceptor(RequestInterceptor requestInterceptor) {
mRequestInterceptors.add(requestInterceptor); mRequestInterceptors.add(requestInterceptor);
return this; return this;
} }
public HttpInterceptor addResponseInterceptor (ResponseInterceptor responseInterceptor) { public HttpInterceptor addResponseInterceptor(ResponseInterceptor responseInterceptor) {
mResponseInterceptors.add(responseInterceptor); mResponseInterceptors.add(responseInterceptor);
return this; return this;
} }
@ -106,4 +99,12 @@ public class HttpInterceptor implements Interceptor {
public ArrayList<ResponseInterceptor> getResponseInterceptors() { public ArrayList<ResponseInterceptor> getResponseInterceptors() {
return mResponseInterceptors; return mResponseInterceptors;
} }
public interface RequestInterceptor {
Request intercept(Request request) throws IOException;
}
public interface ResponseInterceptor {
Response intercept(Response response) throws IOException;
}
} }

View File

@ -25,12 +25,6 @@
package com.owncloud.android.lib.common.http.methods; package com.owncloud.android.lib.common.http.methods;
import com.owncloud.android.lib.common.http.HttpClient; import com.owncloud.android.lib.common.http.HttpClient;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Headers; import okhttp3.Headers;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
@ -39,6 +33,11 @@ import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/** /**
* Wrapper to perform http calls transparently by using: * Wrapper to perform http calls transparently by using:
* - OkHttp for non webdav methods * - OkHttp for non webdav methods
@ -136,6 +135,12 @@ public abstract class HttpBaseMethod {
// Connection parameters // Connection parameters
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
mOkHttpClient = mOkHttpClient.newBuilder()
.retryOnConnectionFailure(retryOnConnectionFailure)
.build();
}
public void setReadTimeout(long readTimeout, TimeUnit timeUnit) { public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
mOkHttpClient = mOkHttpClient.newBuilder() mOkHttpClient = mOkHttpClient.newBuilder()
.readTimeout(readTimeout, timeUnit) .readTimeout(readTimeout, timeUnit)
@ -154,12 +159,6 @@ public abstract class HttpBaseMethod {
.build(); .build();
} }
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
mOkHttpClient = mOkHttpClient.newBuilder()
.retryOnConnectionFailure(retryOnConnectionFailure)
.build();
}
// Request // Request
public void addRequestHeader(String name, String value) { public void addRequestHeader(String name, String value) {

View File

@ -27,13 +27,12 @@ package com.owncloud.android.lib.common.http.methods.nonwebdav;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import okhttp3.HttpUrl;
/** /**
* OkHttp delete calls wrapper * OkHttp delete calls wrapper
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class DeleteMethod extends HttpMethod{ public class DeleteMethod extends HttpMethod {
public DeleteMethod(URL url) { public DeleteMethod(URL url) {
super(url); super(url);

View File

@ -27,10 +27,9 @@ package com.owncloud.android.lib.common.http.methods.nonwebdav;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import okhttp3.HttpUrl;
/** /**
* OkHttp get calls wrapper * OkHttp get calls wrapper
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class GetMethod extends HttpMethod { public class GetMethod extends HttpMethod {

View File

@ -29,9 +29,6 @@ import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import okhttp3.Call;
import okhttp3.HttpUrl;
/** /**
* Wrapper to perform OkHttp calls * Wrapper to perform OkHttp calls
* *

View File

@ -27,15 +27,14 @@ package com.owncloud.android.lib.common.http.methods.nonwebdav;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import okhttp3.HttpUrl;
/** /**
* OkHttp post calls wrapper * OkHttp post calls wrapper
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class PostMethod extends HttpMethod { public class PostMethod extends HttpMethod {
public PostMethod(URL url){ public PostMethod(URL url) {
super(url); super(url);
} }

View File

@ -27,11 +27,9 @@ package com.owncloud.android.lib.common.http.methods.nonwebdav;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import okhttp3.HttpUrl; public class PutMethod extends HttpMethod {
public class PutMethod extends HttpMethod{ public PutMethod(URL url) {
public PutMethod(URL url){
super(url); super(url);
} }

View File

@ -24,12 +24,13 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import java.net.URL;
import kotlin.Unit; import kotlin.Unit;
import java.net.URL;
/** /**
* Copy calls wrapper * Copy calls wrapper
*
* @author Christian Schabesberger * @author Christian Schabesberger
* @author David González Verdugo * @author David González Verdugo
*/ */

View File

@ -24,23 +24,23 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import at.bitfire.dav4android.Constants; import at.bitfire.dav4android.Constants;
import at.bitfire.dav4android.DavOCResource; import at.bitfire.dav4android.DavOCResource;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.exception.RedirectException; import at.bitfire.dav4android.exception.RedirectException;
import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.Protocol; import okhttp3.Protocol;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/** /**
* Wrapper to perform WebDAV (dav4android) calls * Wrapper to perform WebDAV (dav4android) calls
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public abstract class DavMethod extends HttpBaseMethod { public abstract class DavMethod extends HttpBaseMethod {
@ -124,6 +124,24 @@ public abstract class DavMethod extends HttpBaseMethod {
Constants.INSTANCE.getLog()); Constants.INSTANCE.getLog());
} }
@Override
public void setUrl(HttpUrl url) {
super.setUrl(url);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
@Override
public boolean getRetryOnConnectionFailure() {
return false; //TODO: implement me
}
//////////////////////////////
// Getter
//////////////////////////////
@Override @Override
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) { public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
super.setRetryOnConnectionFailure(retryOnConnectionFailure); super.setRetryOnConnectionFailure(retryOnConnectionFailure);
@ -133,24 +151,6 @@ public abstract class DavMethod extends HttpBaseMethod {
Constants.INSTANCE.getLog()); Constants.INSTANCE.getLog());
} }
@Override
public void setUrl(HttpUrl url){
super.setUrl(url);
mDavResource = new DavOCResource(
mOkHttpClient,
HttpUrl.parse(mRequest.url().toString()),
Constants.INSTANCE.getLog());
}
//////////////////////////////
// Getter
//////////////////////////////
@Override
public boolean getRetryOnConnectionFailure() {
return false; //TODO: implement me
}
@Override @Override
public boolean isAborted() { public boolean isAborted() {
return mDavResource.isCallAborted(); return mDavResource.isCallAborted();

View File

@ -24,12 +24,13 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import java.net.URL;
import kotlin.Unit; import kotlin.Unit;
import java.net.URL;
/** /**
* MkCol calls wrapper * MkCol calls wrapper
*
* @author Christian Schabesberger * @author Christian Schabesberger
* @author David González Verdugo * @author David González Verdugo
*/ */

View File

@ -25,13 +25,13 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import kotlin.Unit;
import java.net.URL; import java.net.URL;
import kotlin.Unit;
/** /**
* Move calls wrapper * Move calls wrapper
*
* @author Christian Schabesberger * @author Christian Schabesberger
* @author David González Verdugo * @author David González Verdugo
*/ */

View File

@ -24,18 +24,19 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import at.bitfire.dav4android.Property; import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.Response; import at.bitfire.dav4android.Response;
import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.DavException;
import kotlin.Unit; import kotlin.Unit;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/** /**
* Propfind calls wrapper * Propfind calls wrapper
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class PropfindMethod extends DavMethod { public class PropfindMethod extends DavMethod {
@ -57,7 +58,7 @@ public class PropfindMethod extends DavMethod {
} }
@Override @Override
public int onExecute() throws IOException, DavException{ public int onExecute() throws IOException, DavException {
mDavResource.propfind(mDepth, mPropertiesToRequest, mDavResource.propfind(mDepth, mPropertiesToRequest,
(Response response, Response.HrefRelation hrefRelation) -> { (Response response, Response.HrefRelation hrefRelation) -> {
switch (hrefRelation) { switch (hrefRelation) {

View File

@ -24,23 +24,25 @@
package com.owncloud.android.lib.common.http.methods.webdav; package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.exception.HttpException;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import kotlin.Unit;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import at.bitfire.dav4android.exception.HttpException;
import kotlin.Unit;
/** /**
* Put calls wrapper * Put calls wrapper
*
* @author David González Verdugo * @author David González Verdugo
*/ */
public class PutMethod extends DavMethod { public class PutMethod extends DavMethod {
public PutMethod(URL url) { public PutMethod(URL url) {
super(url); super(url);
}; }
;
@Override @Override
public int onExecute() throws IOException, HttpException { public int onExecute() throws IOException, HttpException {

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,6 +24,11 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import com.owncloud.android.lib.common.utils.Log_OC;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -34,19 +39,11 @@ import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import com.owncloud.android.lib.common.utils.Log_OC;
/** /**
* @author David A. Velasco * @author David A. Velasco
*/ */
public class AdvancedX509TrustManager implements X509TrustManager { public class AdvancedX509TrustManager implements X509TrustManager {
private static final String TAG = AdvancedX509TrustManager.class.getSimpleName(); private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
private X509TrustManager mStandardTrustManager = null; private X509TrustManager mStandardTrustManager = null;
@ -54,27 +51,27 @@ public class AdvancedX509TrustManager implements X509TrustManager {
/** /**
* Constructor for AdvancedX509TrustManager * Constructor for AdvancedX509TrustManager
* *
* @param knownServersKeyStore Local certificates store with server certificates explicitly trusted by the user. * @param knownServersKeyStore Local certificates store with server certificates explicitly trusted by the user.
* @throws CertStoreException When no default X509TrustManager instance was found in the system. * @throws CertStoreException When no default X509TrustManager instance was found in the system.
*/ */
public AdvancedX509TrustManager(KeyStore knownServersKeyStore) public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
throws NoSuchAlgorithmException, KeyStoreException, CertStoreException { throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
super(); super();
TrustManagerFactory factory = TrustManagerFactory TrustManagerFactory factory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm()); .getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore)null); factory.init((KeyStore) null);
mStandardTrustManager = findX509TrustManager(factory); mStandardTrustManager = findX509TrustManager(factory);
mKnownServersKeyStore = knownServersKeyStore; mKnownServersKeyStore = knownServersKeyStore;
} }
/** /**
* Locates the first X509TrustManager provided by a given TrustManagerFactory * Locates the first X509TrustManager provided by a given TrustManagerFactory
* @param factory TrustManagerFactory to inspect in the search for a X509TrustManager *
* @return The first X509TrustManager found in factory. * @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
* @throws CertStoreException When no X509TrustManager instance was found in factory * @return The first X509TrustManager found in factory.
* @throws CertStoreException When no X509TrustManager instance was found in factory
*/ */
private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException { private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
TrustManager tms[] = factory.getTrustManagers(); TrustManager tms[] = factory.getTrustManagers();
@ -85,36 +82,34 @@ public class AdvancedX509TrustManager implements X509TrustManager {
} }
return null; return null;
} }
/** /**
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[], * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
* String authType) * String authType)
*/ */
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException { public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
mStandardTrustManager.checkClientTrusted(certificates, authType); mStandardTrustManager.checkClientTrusted(certificates, authType);
} }
/** /**
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
* String authType) * String authType)
*/ */
public void checkServerTrusted(X509Certificate[] certificates, String authType) { public void checkServerTrusted(X509Certificate[] certificates, String authType) {
if (!isKnownServer(certificates[0])) { if (!isKnownServer(certificates[0])) {
CertificateCombinedException result = new CertificateCombinedException(certificates[0]); CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
try { try {
certificates[0].checkValidity(); certificates[0].checkValidity();
} catch (CertificateExpiredException c) { } catch (CertificateExpiredException c) {
result.setCertificateExpiredException(c); result.setCertificateExpiredException(c);
} catch (CertificateNotYetValidException c) { } catch (CertificateNotYetValidException c) {
result.setCertificateNotYetException(c); result.setCertificateNotYetException(c);
} }
try { try {
mStandardTrustManager.checkServerTrusted(certificates, authType); mStandardTrustManager.checkServerTrusted(certificates, authType);
} catch (CertificateException c) { } catch (CertificateException c) {
Throwable cause = c.getCause(); Throwable cause = c.getCause();
Throwable previousCause = null; Throwable previousCause = null;
while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) { // getCause() is not funny while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) { // getCause() is not funny
@ -122,19 +117,19 @@ public class AdvancedX509TrustManager implements X509TrustManager {
cause = cause.getCause(); cause = cause.getCause();
} }
if (cause != null && cause instanceof CertPathValidatorException) { if (cause != null && cause instanceof CertPathValidatorException) {
result.setCertPathValidatorException((CertPathValidatorException)cause); result.setCertPathValidatorException((CertPathValidatorException) cause);
} else { } else {
result.setOtherCertificateException(c); result.setOtherCertificateException(c);
} }
} }
if (result.isException()) if (result.isException()) {
throw result; throw result;
}
} }
} }
/** /**
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/ */
@ -142,7 +137,6 @@ public class AdvancedX509TrustManager implements X509TrustManager {
return mStandardTrustManager.getAcceptedIssuers(); return mStandardTrustManager.getAcceptedIssuers();
} }
public boolean isKnownServer(X509Certificate cert) { public boolean isKnownServer(X509Certificate cert) {
try { try {
return (mKnownServersKeyStore.getCertificateAlias(cert) != null); return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
@ -151,5 +145,5 @@ public class AdvancedX509TrustManager implements X509TrustManager {
return false; return false;
} }
} }
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,36 +24,37 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import javax.net.ssl.SSLPeerUnverifiedException;
/** /**
* Exception joining all the problems that {@link AdvancedX509TrustManager} can find in * Exception joining all the problems that {@link AdvancedX509TrustManager} can find in
* a certificate chain for a server. * a certificate chain for a server.
* * <p>
* This was initially created as an extension of CertificateException, but some * This was initially created as an extension of CertificateException, but some
* implementations of the SSL socket layer in existing devices are REPLACING the CertificateException * implementations of the SSL socket layer in existing devices are REPLACING the CertificateException
* instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)} * instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)}
* with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it. * with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it.
* * <p>
* Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException * Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException
* instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}. * instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}.
* * <p>
* BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it * BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it
* in client methods. Be sure to use it only when you know exactly where it will go. * in client methods. Be sure to use it only when you know exactly where it will go.
* *
* @author David A. Velasco * @author David A. Velasco
*/ */
public class CertificateCombinedException extends RuntimeException { public class CertificateCombinedException extends RuntimeException {
/** Generated - to refresh every time the class changes */ /**
* Generated - to refresh every time the class changes
*/
private static final long serialVersionUID = -8875782030758554999L; private static final long serialVersionUID = -8875782030758554999L;
private X509Certificate mServerCert = null; private X509Certificate mServerCert = null;
private String mHostInUrl; private String mHostInUrl;
@ -62,7 +63,7 @@ public class CertificateCombinedException extends RuntimeException {
private CertPathValidatorException mCertPathValidatorException = null; private CertPathValidatorException mCertPathValidatorException = null;
private CertificateException mOtherCertificateException = null; private CertificateException mOtherCertificateException = null;
private SSLPeerUnverifiedException mSslPeerUnverifiedException = null; private SSLPeerUnverifiedException mSslPeerUnverifiedException = null;
public CertificateCombinedException(X509Certificate x509Certificate) { public CertificateCombinedException(X509Certificate x509Certificate) {
mServerCert = x509Certificate; mServerCert = x509Certificate;
} }
@ -84,7 +85,7 @@ public class CertificateCombinedException extends RuntimeException {
} }
public void setCertificateExpiredException(CertificateExpiredException c) { public void setCertificateExpiredException(CertificateExpiredException c) {
mCertificateExpiredException = c; mCertificateExpiredException = c;
} }
public CertificateNotYetValidException getCertificateNotYetValidException() { public CertificateNotYetValidException getCertificateNotYetValidException() {
@ -112,7 +113,7 @@ public class CertificateCombinedException extends RuntimeException {
} }
public SSLPeerUnverifiedException getSslPeerUnverifiedException() { public SSLPeerUnverifiedException getSslPeerUnverifiedException() {
return mSslPeerUnverifiedException ; return mSslPeerUnverifiedException;
} }
public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) { public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) {

View File

@ -27,6 +27,8 @@ package com.owncloud.android.lib.common.network;
import android.util.Log; import android.util.Log;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.MediaType;
import okio.BufferedSink;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -34,9 +36,6 @@ import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.Iterator; import java.util.Iterator;
import okhttp3.MediaType;
import okio.BufferedSink;
/** /**
* A Request body that represents a file chunk and include information about the progress when uploading it * A Request body that represents a file chunk and include information about the progress when uploading it
* *
@ -84,18 +83,19 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
try { try {
mChannel.position(mOffset); mChannel.position(mOffset);
long size = mFile.length(); long size = mFile.length();
if (size == 0) size = -1; if (size == 0) {
size = -1;
}
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size()); long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
while (mChannel.position() < maxCount) { while (mChannel.position() < maxCount) {
Log_OC.d(TAG, "Sink buffer size: " + sink.buffer().size()); Log_OC.d(TAG, "Sink buffer size: " + sink.buffer().size());
readCount = mChannel.read(mBuffer); readCount = mChannel.read(mBuffer);
Log_OC.d(TAG, "Read " + readCount + " bytes from file channel to " + mBuffer.toString()); Log_OC.d(TAG, "Read " + readCount + " bytes from file channel to " + mBuffer.toString());
sink.buffer().write(mBuffer.array(), 0 ,readCount); sink.buffer().write(mBuffer.array(), 0, readCount);
sink.flush(); sink.flush();
@ -118,14 +118,14 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
} catch (Exception exception) { } catch (Exception exception) {
Log.e(TAG, exception.toString()); Log.e(TAG, exception.toString());
// // any read problem will be handled as if the file is not there // // any read problem will be handled as if the file is not there
// if (io instanceof FileNotFoundException) { // if (io instanceof FileNotFoundException) {
// throw io; // throw io;
// } else { // } else {
// FileNotFoundException fnf = new FileNotFoundException("Exception reading source file"); // FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
// fnf.initCause(io); // fnf.initCause(io);
// throw fnf; // throw fnf;
// } // }
} }
} }

View File

@ -26,7 +26,11 @@ package com.owncloud.android.lib.common.network;
import android.util.Log; import android.util.Log;
import com.owncloud.android.lib.common.utils.Log_OC; import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.Collection;
@ -34,12 +38,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
/** /**
* A Request body that represents a file and include information about the progress when uploading it * A Request body that represents a file and include information about the progress when uploading it
* *

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,6 +24,11 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import android.content.Context;
import com.owncloud.android.lib.common.utils.Log_OC;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -35,54 +40,50 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import android.content.Context;
import com.owncloud.android.lib.common.utils.Log_OC;
public class NetworkUtils { public class NetworkUtils {
final private static String TAG = NetworkUtils.class.getSimpleName();
/** Default timeout for waiting data from the server */
public static final int DEFAULT_DATA_TIMEOUT = 60000;
/** Default timeout for establishing a connection */
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
/** Standard name for protocol TLS version 1.2 in Java Secure Socket Extension (JSSE) API */
public static final String PROTOCOL_TLSv1_2 = "TLSv1.2";
/** Standard name for protocol TLS version 1.0 in JSSE API */
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
/**
* Default timeout for waiting data from the server
*/
public static final int DEFAULT_DATA_TIMEOUT = 60000;
/**
* Default timeout for establishing a connection
*/
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
/**
* Standard name for protocol TLS version 1.2 in Java Secure Socket Extension (JSSE) API
*/
public static final String PROTOCOL_TLSv1_2 = "TLSv1.2";
/**
* Standard name for protocol TLS version 1.0 in JSSE API
*/
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
final private static String TAG = NetworkUtils.class.getSimpleName();
private static X509HostnameVerifier mHostnameVerifier = null; private static X509HostnameVerifier mHostnameVerifier = null;
private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks"; private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
private static String LOCAL_TRUSTSTORE_PASSWORD = "password"; private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
private static KeyStore mKnownServersStore = null; private static KeyStore mKnownServersStore = null;
/** /**
* Returns the local store of reliable server certificates, explicitly accepted by the user. * Returns the local store of reliable server certificates, explicitly accepted by the user.
* * <p>
* Returns a KeyStore instance with empty content if the local store was never created. * Returns a KeyStore instance with empty content if the local store was never created.
* * <p>
* Loads the store from the storage environment if needed. * Loads the store from the storage environment if needed.
* *
* @param context Android context where the operation is being performed. * @param context Android context where the operation is being performed.
* @return KeyStore instance with explicitly-accepted server certificates. * @return KeyStore instance with explicitly-accepted server certificates.
* @throws KeyStoreException When the KeyStore instance could not be created. * @throws KeyStoreException When the KeyStore instance could not be created.
* @throws IOException When an existing local trust store could not be loaded. * @throws IOException When an existing local trust store could not be loaded.
* @throws NoSuchAlgorithmException When the existing local trust store was saved with an unsupported algorithm. * @throws NoSuchAlgorithmException When the existing local trust store was saved with an unsupported algorithm.
* @throws CertificateException When an exception occurred while loading the certificates from the local * @throws CertificateException When an exception occurred while loading the certificates from the local
* trust store. * trust store.
*/ */
public static KeyStore getKnownServersStore(Context context) public static KeyStore getKnownServersStore(Context context)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
if (mKnownServersStore == null) { if (mKnownServersStore == null) {
//mKnownServersStore = KeyStore.getInstance("BKS"); //mKnownServersStore = KeyStore.getInstance("BKS");
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType()); mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
@ -96,17 +97,16 @@ public class NetworkUtils {
in.close(); in.close();
} }
} else { } else {
// next is necessary to initialize an empty KeyStore instance // next is necessary to initialize an empty KeyStore instance
mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
} }
} }
return mKnownServersStore; return mKnownServersStore;
} }
public static void addCertToKnownServersStore(Certificate cert, Context context)
public static void addCertToKnownServersStore(Certificate cert, Context context) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore knownServers = getKnownServersStore(context); KeyStore knownServers = getKnownServersStore(context);
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert); knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
FileOutputStream fos = null; FileOutputStream fos = null;
@ -118,13 +118,13 @@ public class NetworkUtils {
} }
} }
public static boolean isCertInKnownServersStore(Certificate cert, Context context) public static boolean isCertInKnownServersStore(Certificate cert, Context context)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore knownServers = getKnownServersStore(context); KeyStore knownServers = getKnownServersStore(context);
Log_OC.d(TAG, "Certificate - HashCode: " + cert.hashCode() + " " Log_OC.d(TAG, "Certificate - HashCode: " + cert.hashCode() + " "
+ Boolean.toString(knownServers.isCertificateEntry(Integer.toString(cert.hashCode())))); + Boolean.toString(knownServers.isCertificateEntry(Integer.toString(cert.hashCode()))));
return knownServers.isCertificateEntry(Integer.toString(cert.hashCode())); return knownServers.isCertificateEntry(Integer.toString(cert.hashCode()));
} }
} }

View File

@ -1,23 +1,23 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -26,11 +26,10 @@ package com.owncloud.android.lib.common.network;
import java.util.Collection; import java.util.Collection;
public interface ProgressiveDataTransferer { public interface ProgressiveDataTransferer {
public void addDatatransferProgressListener (OnDatatransferProgressListener listener); public void addDatatransferProgressListener(OnDatatransferProgressListener listener);
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners); public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener); public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);

View File

@ -27,22 +27,19 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a * Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
* {@link RemoteOperation}, and the status codes corresponding to all * {@link RemoteOperation}, and the status codes corresponding to all
* of them. * of them.
* * <p>
* The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds * The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
* the maximum length of redirections allowed by the {@link com.owncloud.android.lib.common.OwnCloudClient} instance * the maximum length of redirections allowed by the {@link com.owncloud.android.lib.common.OwnCloudClient} instance
* that ran the operation. * that ran the operation.
* * <p>
* If no redirection was followed, the last (and first) status code contained corresponds to the original URL in the * If no redirection was followed, the last (and first) status code contained corresponds to the original URL in the
* request. * request.
*/ */
@ -59,9 +56,9 @@ public class RedirectionPath {
/** /**
* Public constructor. * Public constructor.
* *
* @param status Status code resulting of executing a request on the original URL. * @param status Status code resulting of executing a request on the original URL.
* @param maxRedirections Maximum number of redirections that will be contained. * @param maxRedirections Maximum number of redirections that will be contained.
* @throws IllegalArgumentException If 'maxRedirections' is < 0 * @throws IllegalArgumentException If 'maxRedirections' is < 0
*/ */
public RedirectionPath(int status, int maxRedirections) { public RedirectionPath(int status, int maxRedirections) {
if (maxRedirections < 0) { if (maxRedirections < 0) {
@ -75,7 +72,7 @@ public class RedirectionPath {
/** /**
* Adds a new location URL to the list of followed redirections. * Adds a new location URL to the list of followed redirections.
* *
* @param location URL extracted from a 'Location' header in a redirection. * @param location URL extracted from a 'Location' header in a redirection.
*/ */
public void addLocation(String location) { public void addLocation(String location) {
if (mLocations == null) { if (mLocations == null) {
@ -86,11 +83,10 @@ public class RedirectionPath {
} }
} }
/** /**
* Adds a new status code to the list of status corresponding to followed redirections. * Adds a new status code to the list of status corresponding to followed redirections.
* *
* @param status Status code from the response of another followed redirection. * @param status Status code from the response of another followed redirection.
*/ */
public void addStatus(int status) { public void addStatus(int status) {
if (mLastStatus < mStatuses.length - 1) { if (mLastStatus < mStatuses.length - 1) {
@ -99,14 +95,14 @@ public class RedirectionPath {
} }
/** /**
* @return Last status code saved. * @return Last status code saved.
*/ */
public int getLastStatus() { public int getLastStatus() {
return mStatuses[mLastStatus]; return mStatuses[mLastStatus];
} }
/** /**
* @return Last location followed corresponding to a permanent redirection (status code 301). * @return Last location followed corresponding to a permanent redirection (status code 301).
*/ */
public String getLastPermanentLocation() { public String getLastPermanentLocation() {
for (int i = mLastStatus; i >= 0; i--) { for (int i = mLastStatus; i >= 0; i--) {
@ -118,11 +114,10 @@ public class RedirectionPath {
} }
/** /**
* @return Count of locations. * @return Count of locations.
*/ */
public int getRedirectionsCount() { public int getRedirectionsCount() {
return mLastLocation + 1; return mLastLocation + 1;
} }
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,128 +24,122 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import com.owncloud.android.lib.common.utils.Log_OC;
import javax.net.ssl.SSLSocket;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSocket;
import com.owncloud.android.lib.common.utils.Log_OC;
/** /**
* Enables the support of Server Name Indication if existing * Enables the support of Server Name Indication if existing
* in the underlying network implementation. * in the underlying network implementation.
* * <p>
* Build as a singleton. * Build as a singleton.
* *
* @author David A. Velasco * @author David A. Velasco
*/ */
public class ServerNameIndicator { public class ServerNameIndicator {
private static final String TAG = ServerNameIndicator.class.getSimpleName();
private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
private static final String METHOD_NAME = "setHostname";
private final WeakReference<Class<?>> mSSLSocketClassRef;
private final WeakReference<Method> mSetHostnameMethodRef;
/**
* Private constructor, class is a singleton.
*
* @param sslSocketClass Underlying implementation class of {@link SSLSocket} used to connect with the server.
* @param setHostnameMethod Name of the method to call to enable the SNI support.
*/
private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
}
/**
* Calls the {@code #setHostname(String)} method of the underlying implementation
* of {@link SSLSocket} if exists.
*
* Creates and initializes the single instance of the class when needed
*
* @param hostname The name of the server host of interest.
* @param sslSocket Client socket to connect with the server.
*/
public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
final Method setHostnameMethod = getMethod(sslSocket);
if (setHostnameMethod != null) {
try {
setHostnameMethod.invoke(sslSocket, hostname);
Log_OC.i(TAG, "SNI done, hostname: " + hostname);
} catch (IllegalArgumentException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (IllegalAccessException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (InvocationTargetException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
}
} else {
Log_OC.i(TAG, "SNI not supported");
}
}
private static final String TAG = ServerNameIndicator.class.getSimpleName();
/**
* Gets the method to invoke trying to minimize the effective
* application of reflection.
*
* @param sslSocket Instance of the SSL socket to use in connection with server.
* @return Method to call to indicate the server name of interest to the server.
*/
private static Method getMethod(SSLSocket sslSocket) {
final Class<?> sslSocketClass = sslSocket.getClass();
final ServerNameIndicator instance = mSingleInstance.get();
if (instance == null) {
return initFrom(sslSocketClass);
} else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
// the underlying class changed
return initFrom(sslSocketClass);
} else if (instance.mSetHostnameMethodRef == null) {
// SNI not supported
return null;
} else {
final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
}
}
private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
/** private static final String METHOD_NAME = "setHostname";
* Singleton initializer.
* private final WeakReference<Class<?>> mSSLSocketClassRef;
* Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side. private final WeakReference<Method> mSetHostnameMethodRef;
*
* @param sslSocketClass Underlying class providing the implementation of {@link SSLSocket}. /**
* @return Method to call to indicate the server name of interest to the server. * Private constructor, class is a singleton.
*/ *
private static Method initFrom(Class<?> sslSocketClass) { * @param sslSocketClass Underlying implementation class of {@link SSLSocket} used to connect with the server.
* @param setHostnameMethod Name of the method to call to enable the SNI support.
*/
private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
}
/**
* Calls the {@code #setHostname(String)} method of the underlying implementation
* of {@link SSLSocket} if exists.
* <p>
* Creates and initializes the single instance of the class when needed
*
* @param hostname The name of the server host of interest.
* @param sslSocket Client socket to connect with the server.
*/
public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
final Method setHostnameMethod = getMethod(sslSocket);
if (setHostnameMethod != null) {
try {
setHostnameMethod.invoke(sslSocket, hostname);
Log_OC.i(TAG, "SNI done, hostname: " + hostname);
} catch (IllegalArgumentException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (IllegalAccessException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (InvocationTargetException e) {
Log_OC.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
}
} else {
Log_OC.i(TAG, "SNI not supported");
}
}
/**
* Gets the method to invoke trying to minimize the effective
* application of reflection.
*
* @param sslSocket Instance of the SSL socket to use in connection with server.
* @return Method to call to indicate the server name of interest to the server.
*/
private static Method getMethod(SSLSocket sslSocket) {
final Class<?> sslSocketClass = sslSocket.getClass();
final ServerNameIndicator instance = mSingleInstance.get();
if (instance == null) {
return initFrom(sslSocketClass);
} else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
// the underlying class changed
return initFrom(sslSocketClass);
} else if (instance.mSetHostnameMethodRef == null) {
// SNI not supported
return null;
} else {
final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
}
}
/**
* Singleton initializer.
* <p>
* Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side.
*
* @param sslSocketClass Underlying class providing the implementation of {@link SSLSocket}.
* @return Method to call to indicate the server name of interest to the server.
*/
private static Method initFrom(Class<?> sslSocketClass) {
Log_OC.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName()); Log_OC.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName());
Method setHostnameMethod = null; Method setHostnameMethod = null;
try { try {
setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class); setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class);
} catch (SecurityException e) { } catch (SecurityException e) {
Log_OC.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e); Log_OC.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
Log_OC.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported"); Log_OC.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported");
} }
mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod)); mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod));
return setHostnameMethod; return setHostnameMethod;
} }
} }

View File

@ -1,23 +1,23 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -25,64 +25,64 @@
package com.owncloud.android.lib.common.network; package com.owncloud.android.lib.common.network;
import android.net.Uri;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import android.net.Uri;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
public class WebdavUtils { public class WebdavUtils {
public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat( public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
"dd.MM.yyyy hh:mm"); "dd.MM.yyyy hh:mm");
private static final SimpleDateFormat DATETIME_FORMATS[] = { private static final SimpleDateFormat DATETIME_FORMATS[] = {
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US),
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US), new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US),
new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US), new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US),
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.US) new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.US)
}; };
public static Date parseResponseDate(String date) { public static Date parseResponseDate(String date) {
Date returnDate = null; Date returnDate = null;
SimpleDateFormat format = null; SimpleDateFormat format = null;
for (int i = 0; i < DATETIME_FORMATS.length; ++i) { for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
try { try {
format = DATETIME_FORMATS[i]; format = DATETIME_FORMATS[i];
synchronized(format) { synchronized (format) {
returnDate = format.parse(date); returnDate = format.parse(date);
} }
return returnDate; return returnDate;
} catch (ParseException e) { } catch (ParseException e) {
// this is not the format // this is not the format
} }
} }
return null; return null;
} }
/** /**
* Encodes a path according to URI RFC 2396. * Encodes a path according to URI RFC 2396.
* * <p>
* If the received path doesn't start with "/", the method adds it. * If the received path doesn't start with "/", the method adds it.
* *
* @param remoteFilePath Path * @param remoteFilePath Path
* @return Encoded path according to RFC 2396, always starting with "/" * @return Encoded path according to RFC 2396, always starting with "/"
*/ */
public static String encodePath(String remoteFilePath) { public static String encodePath(String remoteFilePath) {
String encodedPath = Uri.encode(remoteFilePath, "/"); String encodedPath = Uri.encode(remoteFilePath, "/");
if (!encodedPath.startsWith("/")) if (!encodedPath.startsWith("/")) {
encodedPath = "/" + encodedPath; encodedPath = "/" + encodedPath;
}
return encodedPath; return encodedPath;
} }
/** /**
*
* @param rawEtag * @param rawEtag
* @return * @return
*/ */
@ -100,7 +100,6 @@ public class WebdavUtils {
} }
/** /**
*
* @param httpBaseMethod from which to get the etag * @param httpBaseMethod from which to get the etag
* @return etag from response * @return etag from response
*/ */

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2017 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -32,18 +32,17 @@ import java.lang.reflect.Method;
import java.net.Socket; import java.net.Socket;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
/** /**
* Enforces, if possible, a write timeout for a socket. * Enforces, if possible, a write timeout for a socket.
* * <p>
* Built as a singleton. * Built as a singleton.
* * <p>
* Tries to hit something like this: * Tries to hit something like this:
* https://android.googlesource.com/platform/external/conscrypt/+/lollipop-release/src/main/java/org/conscrypt/OpenSSLSocketImpl.java#1005 * https://android.googlesource.com/platform/external/conscrypt/+/lollipop-release/src/main/java/org/conscrypt/OpenSSLSocketImpl.java#1005
* * <p>
* Minimizes the chances of getting stalled in PUT/POST request if the network interface is lost while * Minimizes the chances of getting stalled in PUT/POST request if the network interface is lost while
* writing the entity into the outwards sockect. * writing the entity into the outwards sockect.
* * <p>
* It happens. See https://github.com/owncloud/android/issues/1684#issuecomment-295306015 * It happens. See https://github.com/owncloud/android/issues/1684#issuecomment-295306015
* *
* @author David A. Velasco * @author David A. Velasco
@ -56,36 +55,33 @@ public class WriteTimeoutEnforcer {
private static final String METHOD_NAME = "setSoWriteTimeout"; private static final String METHOD_NAME = "setSoWriteTimeout";
private final WeakReference<Class<?>> mSocketClassRef; private final WeakReference<Class<?>> mSocketClassRef;
private final WeakReference<Method> mSetSoWriteTimeoutMethodRef; private final WeakReference<Method> mSetSoWriteTimeoutMethodRef;
/** /**
* Private constructor, class is a singleton. * Private constructor, class is a singleton.
* *
* @param socketClass Underlying implementation class of {@link Socket} used to connect * @param socketClass Underlying implementation class of {@link Socket} used to connect
* with the server. * with the server.
* @param setSoWriteTimeoutMethod Name of the method to call to set a write timeout in the socket. * @param setSoWriteTimeoutMethod Name of the method to call to set a write timeout in the socket.
*/ */
private WriteTimeoutEnforcer(Class<?> socketClass, Method setSoWriteTimeoutMethod) { private WriteTimeoutEnforcer(Class<?> socketClass, Method setSoWriteTimeoutMethod) {
mSocketClassRef = new WeakReference<Class<?>>(socketClass); mSocketClassRef = new WeakReference<Class<?>>(socketClass);
mSetSoWriteTimeoutMethodRef = mSetSoWriteTimeoutMethodRef =
(setSoWriteTimeoutMethod == null) ? (setSoWriteTimeoutMethod == null) ?
null : null :
new WeakReference<>(setSoWriteTimeoutMethod) new WeakReference<>(setSoWriteTimeoutMethod)
; ;
} }
/** /**
* Calls the {@code #setSoWrite(int)} method of the underlying implementation * Calls the {@code #setSoWrite(int)} method of the underlying implementation
* of {@link Socket} if exists. * of {@link Socket} if exists.
* <p>
* Creates and initializes the single instance of the class when needed * Creates and initializes the single instance of the class when needed
* *
* @param writeTimeoutMilliseconds Write timeout to set, in milliseconds. * @param writeTimeoutMilliseconds Write timeout to set, in milliseconds.
* @param socket Client socket to connect with the server. * @param socket Client socket to connect with the server.
*/ */
public static void setSoWriteTimeout(int writeTimeoutMilliseconds, Socket socket) { public static void setSoWriteTimeout(int writeTimeoutMilliseconds, Socket socket) {
final Method setSoWriteTimeoutMethod = getMethod(socket); final Method setSoWriteTimeoutMethod = getMethod(socket);
@ -93,9 +89,9 @@ public class WriteTimeoutEnforcer {
try { try {
setSoWriteTimeoutMethod.invoke(socket, writeTimeoutMilliseconds); setSoWriteTimeoutMethod.invoke(socket, writeTimeoutMilliseconds);
Log_OC.i( Log_OC.i(
TAG, TAG,
"Write timeout set in socket, writeTimeoutMilliseconds: " "Write timeout set in socket, writeTimeoutMilliseconds: "
+ writeTimeoutMilliseconds + writeTimeoutMilliseconds
); );
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@ -112,13 +108,12 @@ public class WriteTimeoutEnforcer {
} }
} }
/** /**
* Gets the method to invoke trying to minimize the cost of reflection reusing objects cached * Gets the method to invoke trying to minimize the cost of reflection reusing objects cached
* in static members. * in static members.
* *
* @param socket Instance of the socket to use in connection with server. * @param socket Instance of the socket to use in connection with server.
* @return Method to call to set a write timeout in the socket. * @return Method to call to set a write timeout in the socket.
*/ */
private static Method getMethod(Socket socket) { private static Method getMethod(Socket socket) {
final Class<?> socketClass = socket.getClass(); final Class<?> socketClass = socket.getClass();
@ -137,20 +132,19 @@ public class WriteTimeoutEnforcer {
} else { } else {
final Method cachedSetSoWriteTimeoutMethod = instance.mSetSoWriteTimeoutMethodRef.get(); final Method cachedSetSoWriteTimeoutMethod = instance.mSetSoWriteTimeoutMethodRef.get();
return (cachedSetSoWriteTimeoutMethod == null) ? return (cachedSetSoWriteTimeoutMethod == null) ?
initFrom(socketClass) : initFrom(socketClass) :
cachedSetSoWriteTimeoutMethod cachedSetSoWriteTimeoutMethod
; ;
} }
} }
/** /**
* Singleton initializer. * Singleton initializer.
* * <p>
* Uses reflection to extract and 'cache' the method to invoke to set a write timouet in a socket. * Uses reflection to extract and 'cache' the method to invoke to set a write timouet in a socket.
* *
* @param socketClass Underlying class providing the implementation of {@link Socket}. * @param socketClass Underlying class providing the implementation of {@link Socket}.
* @return Method to call to set a write timeout in the socket. * @return Method to call to set a write timeout in the socket.
*/ */
private static Method initFrom(Class<?> socketClass) { private static Method initFrom(Class<?> socketClass) {
Log_OC.i(TAG, "Socket implementation: " + socketClass.getCanonicalName()); Log_OC.i(TAG, "Socket implementation: " + socketClass.getCanonicalName());
@ -162,8 +156,8 @@ public class WriteTimeoutEnforcer {
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
Log_OC.i( Log_OC.i(
TAG, TAG,
"Could not find (SocketImpl)#setSoWriteTimeout(int) method - write timeout not supported" "Could not find (SocketImpl)#setSoWriteTimeout(int) method - write timeout not supported"
); );
} }
mSingleInstance.set(new WriteTimeoutEnforcer(socketClass, setSoWriteTimeoutMethod)); mSingleInstance.set(new WriteTimeoutEnforcer(socketClass, setSoWriteTimeoutMethod));

View File

@ -34,105 +34,110 @@ import java.io.InputStream;
/** /**
* Parser for server exceptions * Parser for server exceptions
*
* @author davidgonzalez * @author davidgonzalez
*/ */
public class ErrorMessageParser { public class ErrorMessageParser {
// No namespaces // No namespaces
private static final String ns = null; private static final String ns = null;
// Nodes for XML Parser // Nodes for XML Parser
private static final String NODE_ERROR = "d:error"; private static final String NODE_ERROR = "d:error";
private static final String NODE_MESSAGE = "s:message"; private static final String NODE_MESSAGE = "s:message";
/** /**
* Parse exception response * Parse exception response
* @param is *
* @return errorMessage for an exception * @param is
* @throws XmlPullParserException * @return errorMessage for an exception
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
public String parseXMLResponse(InputStream is) throws XmlPullParserException, */
IOException { public String parseXMLResponse(InputStream is) throws XmlPullParserException,
String errorMessage = ""; IOException {
String errorMessage = "";
try { try {
// XMLPullParser // XMLPullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true); factory.setNamespaceAware(true);
XmlPullParser parser = Xml.newPullParser(); XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, null); parser.setInput(is, null);
parser.nextTag(); parser.nextTag();
errorMessage = readError(parser); errorMessage = readError(parser);
} finally { } finally {
is.close(); is.close();
} }
return errorMessage; return errorMessage;
} }
/** /**
* Parse OCS node * Parse OCS node
* @param parser *
* @return reason for exception * @param parser
* @throws XmlPullParserException * @return reason for exception
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
private String readError (XmlPullParser parser) throws XmlPullParserException, IOException { */
String errorMessage = ""; private String readError(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR); String errorMessage = "";
while (parser.next() != XmlPullParser.END_TAG) { parser.require(XmlPullParser.START_TAG, ns, NODE_ERROR);
if (parser.getEventType() != XmlPullParser.START_TAG) { while (parser.next() != XmlPullParser.END_TAG) {
continue; if (parser.getEventType() != XmlPullParser.START_TAG) {
} continue;
String name = parser.getName(); }
// read NODE_MESSAGE String name = parser.getName();
if (name.equalsIgnoreCase(NODE_MESSAGE)) { // read NODE_MESSAGE
errorMessage = readText(parser); if (name.equalsIgnoreCase(NODE_MESSAGE)) {
} else { errorMessage = readText(parser);
skip(parser); } else {
} skip(parser);
} }
return errorMessage; }
} return errorMessage;
}
/** /**
* Skip tags in parser procedure * Skip tags in parser procedure
* @param parser *
* @throws XmlPullParserException * @param parser
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { */
if (parser.getEventType() != XmlPullParser.START_TAG) { private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
throw new IllegalStateException(); if (parser.getEventType() != XmlPullParser.START_TAG) {
} throw new IllegalStateException();
int depth = 1; }
while (depth != 0) { int depth = 1;
switch (parser.next()) { while (depth != 0) {
case XmlPullParser.END_TAG: switch (parser.next()) {
depth--; case XmlPullParser.END_TAG:
break; depth--;
case XmlPullParser.START_TAG: break;
depth++; case XmlPullParser.START_TAG:
break; depth++;
} break;
} }
} }
}
/** /**
* Read the text from a node * Read the text from a node
* @param parser *
* @return Text of the node * @param parser
* @throws IOException * @return Text of the node
* @throws XmlPullParserException * @throws IOException
*/ * @throws XmlPullParserException
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException { */
String result = ""; private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
if (parser.next() == XmlPullParser.TEXT) { String result = "";
result = parser.getText(); if (parser.next() == XmlPullParser.TEXT) {
parser.nextTag(); result = parser.getText();
} parser.nextTag();
return result; }
} return result;
}
} }

View File

@ -35,110 +35,116 @@ import java.io.InputStream;
/** /**
* Parser for Invalid Character server exception * Parser for Invalid Character server exception
*
* @author masensio * @author masensio
*/ */
public class InvalidCharacterExceptionParser { public class InvalidCharacterExceptionParser {
private static final String EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath"; private static final String EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath";
private static final String EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException"; private static final String EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException";
// No namespaces // No namespaces
private static final String ns = null; private static final String ns = null;
// Nodes for XML Parser // Nodes for XML Parser
private static final String NODE_ERROR = "d:error"; private static final String NODE_ERROR = "d:error";
private static final String NODE_EXCEPTION = "s:exception"; private static final String NODE_EXCEPTION = "s:exception";
/** /**
* Parse is as an Invalid Path Exception * Parse is as an Invalid Path Exception
* @param is *
* @return if The exception is an Invalid Char Exception * @param is
* @throws XmlPullParserException * @return if The exception is an Invalid Char Exception
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
public boolean parseXMLResponse(InputStream is) throws XmlPullParserException, */
public boolean parseXMLResponse(InputStream is) throws XmlPullParserException,
IOException { IOException {
boolean result = false; boolean result = false;
try { try {
// XMLPullParser // XMLPullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true); factory.setNamespaceAware(true);
XmlPullParser parser = Xml.newPullParser(); XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, null); parser.setInput(is, null);
parser.nextTag(); parser.nextTag();
result = readError(parser); result = readError(parser);
} finally { } finally {
is.close(); is.close();
} }
return result; return result;
} }
/** /**
* Parse OCS node * Parse OCS node
* @param parser *
* @return List of ShareRemoteFiles * @param parser
* @throws XmlPullParserException * @return List of ShareRemoteFiles
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
private boolean readError (XmlPullParser parser) throws XmlPullParserException, IOException { */
String exception = ""; private boolean readError(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR); String exception = "";
while (parser.next() != XmlPullParser.END_TAG) { parser.require(XmlPullParser.START_TAG, ns, NODE_ERROR);
if (parser.getEventType() != XmlPullParser.START_TAG) { while (parser.next() != XmlPullParser.END_TAG) {
continue; if (parser.getEventType() != XmlPullParser.START_TAG) {
} continue;
String name = parser.getName(); }
// read NODE_EXCEPTION String name = parser.getName();
if (name.equalsIgnoreCase(NODE_EXCEPTION)) { // read NODE_EXCEPTION
exception = readText(parser); if (name.equalsIgnoreCase(NODE_EXCEPTION)) {
} else { exception = readText(parser);
skip(parser); } else {
} skip(parser);
}
} }
return exception.equalsIgnoreCase(EXCEPTION_STRING) || return exception.equalsIgnoreCase(EXCEPTION_STRING) ||
exception.equalsIgnoreCase(EXCEPTION_UPLOAD_STRING); exception.equalsIgnoreCase(EXCEPTION_UPLOAD_STRING);
} }
/** /**
* Skip tags in parser procedure * Skip tags in parser procedure
* @param parser *
* @throws XmlPullParserException * @param parser
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { */
if (parser.getEventType() != XmlPullParser.START_TAG) { private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
throw new IllegalStateException(); if (parser.getEventType() != XmlPullParser.START_TAG) {
} throw new IllegalStateException();
int depth = 1; }
while (depth != 0) { int depth = 1;
switch (parser.next()) { while (depth != 0) {
case XmlPullParser.END_TAG: switch (parser.next()) {
depth--; case XmlPullParser.END_TAG:
break; depth--;
case XmlPullParser.START_TAG: break;
depth++; case XmlPullParser.START_TAG:
break; depth++;
} break;
} }
} }
}
/** /**
* Read the text from a node * Read the text from a node
* @param parser *
* @return Text of the node * @param parser
* @throws IOException * @return Text of the node
* @throws XmlPullParserException * @throws IOException
*/ * @throws XmlPullParserException
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException { */
String result = ""; private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
if (parser.next() == XmlPullParser.TEXT) { String result = "";
result = parser.getText(); if (parser.next() == XmlPullParser.TEXT) {
parser.nextTag(); result = parser.getText();
} parser.nextTag();
return result; }
} return result;
}
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,9 +24,8 @@
package com.owncloud.android.lib.common.operations; package com.owncloud.android.lib.common.operations;
public interface OnRemoteOperationListener { public interface OnRemoteOperationListener {
void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result); void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *

View File

@ -12,25 +12,21 @@ import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.OkHttpClient;
import java.io.IOException; import java.io.IOException;
import okhttp3.OkHttpClient;
public abstract class RemoteOperation<T extends Object> implements Runnable { public abstract class RemoteOperation<T extends Object> implements Runnable {
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";
private static final String TAG = RemoteOperation.class.getSimpleName();
/** /**
* ownCloud account in the remote ownCloud server to operate * ownCloud account in the remote ownCloud server to operate
*/ */
@ -61,10 +57,9 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
*/ */
protected Handler mListenerHandler = null; protected Handler mListenerHandler = null;
/** /**
* Asynchronously executes the remote operation * Asynchronously executes the remote operation
* * <p>
* 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))}.
* *
@ -79,12 +74,14 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
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 and mContext in the runnerThread to create below
mAccount = account; mAccount = account;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
@ -99,7 +96,6 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
return runnerThread; return runnerThread;
} }
/** /**
* Asynchronously executes the remote operation * Asynchronously executes the remote operation
* *
@ -168,9 +164,9 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
/** /**
* Synchronously executes the remote operation on the received ownCloud account. * Synchronously executes the remote operation on the received ownCloud account.
* * <p>
* Do not call this method from the main thread. * Do not call this method from the main thread.
* * <p>
* 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)}.
* *
@ -180,22 +176,23 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
* @return Result of the operation. * @return Result of the operation.
*/ */
public RemoteOperationResult<T> execute(Account account, Context context) { public RemoteOperationResult<T> execute(Account account, Context context) {
if (account == null) if (account == null) {
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " + throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
"Account"); "Account");
if (context == null) }
if (context == null) {
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " + throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
"Context"); "Context");
}
mAccount = account; mAccount = account;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
return runOperation(); return runOperation();
} }
/** /**
* Synchronously executes the remote operation * Synchronously executes the remote operation
* * <p>
* Do not call this method from the main thread. * Do not call this method from the main thread.
* *
* @param client Client object to reach an ownCloud server during the execution of * @param client Client object to reach an ownCloud server during the execution of
@ -203,9 +200,10 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
* @return Result of the operation. * @return Result of the operation.
*/ */
public RemoteOperationResult<T> execute(OwnCloudClient client) { public RemoteOperationResult<T> execute(OwnCloudClient client) {
if (client == null) if (client == null) {
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " + throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
"OwnCloudClient"); "OwnCloudClient");
}
mClient = client; mClient = client;
if (client.getAccount() != null) { if (client.getAccount() != null) {
mAccount = client.getAccount().getSavedAccount(); mAccount = client.getAccount().getSavedAccount();
@ -217,7 +215,7 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
/** /**
* Synchronously executes the remote operation * Synchronously executes the remote operation
* * <p>
* Do not call this method from the main thread. * Do not call this method from the main thread.
* *
* @param client Client object to reach an ownCloud server during the execution of * @param client Client object to reach an ownCloud server during the execution of
@ -225,9 +223,10 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
* @return Result of the operation. * @return Result of the operation.
*/ */
public RemoteOperationResult<T> execute(OkHttpClient client, Context context) { public RemoteOperationResult<T> execute(OkHttpClient client, Context context) {
if (client == null) if (client == null) {
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " + throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
"OwnCloudClient"); "OwnCloudClient");
}
mHttpClient = client; mHttpClient = client;
mContext = context; mContext = context;
@ -236,12 +235,12 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
/** /**
* Run operation for asynchronous or synchronous 'onExecute' method. * Run operation for asynchronous or synchronous 'onExecute' method.
* * <p>
* Considers and performs silent refresh of account credentials if possible, and if * Considers and performs silent refresh of account credentials if possible, and if
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with * {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
* parameter 'true' before the execution. * parameter 'true' before the execution.
* *
* @return Remote operation result * @return Remote operation result
*/ */
private RemoteOperationResult<T> runOperation() { private RemoteOperationResult<T> runOperation() {

View File

@ -27,14 +27,18 @@ package com.owncloud.android.lib.common.operations;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod; import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
import com.owncloud.android.lib.common.network.CertificateCombinedException; import com.owncloud.android.lib.common.network.CertificateCombinedException;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.Headers;
import org.json.JSONException; import org.json.JSONException;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
@ -48,13 +52,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import okhttp3.Headers;
public class RemoteOperationResult<T extends Object> public class RemoteOperationResult<T extends Object>
implements Serializable { implements Serializable {
@ -64,61 +61,6 @@ public class RemoteOperationResult<T extends Object>
private static final long serialVersionUID = 4968939884332372230L; private static final long serialVersionUID = 4968939884332372230L;
private static final String TAG = RemoteOperationResult.class.getSimpleName(); private static final String TAG = RemoteOperationResult.class.getSimpleName();
public enum ResultCode {
OK,
OK_SSL,
OK_NO_SSL,
UNHANDLED_HTTP_CODE,
UNAUTHORIZED,
FILE_NOT_FOUND,
INSTANCE_NOT_CONFIGURED,
UNKNOWN_ERROR,
WRONG_CONNECTION,
TIMEOUT,
INCORRECT_ADDRESS,
HOST_NOT_AVAILABLE,
NO_NETWORK_CONNECTION,
SSL_ERROR,
SSL_RECOVERABLE_PEER_UNVERIFIED,
BAD_OC_VERSION,
CANCELLED,
INVALID_LOCAL_FILE_NAME,
INVALID_OVERWRITE,
CONFLICT,
OAUTH2_ERROR,
SYNC_CONFLICT,
LOCAL_STORAGE_FULL,
LOCAL_STORAGE_NOT_MOVED,
LOCAL_STORAGE_NOT_COPIED,
OAUTH2_ERROR_ACCESS_DENIED,
QUOTA_EXCEEDED,
ACCOUNT_NOT_FOUND,
ACCOUNT_EXCEPTION,
ACCOUNT_NOT_NEW,
ACCOUNT_NOT_THE_SAME,
INVALID_CHARACTER_IN_NAME,
SHARE_NOT_FOUND,
LOCAL_STORAGE_NOT_REMOVED,
FORBIDDEN,
SHARE_FORBIDDEN,
SPECIFIC_FORBIDDEN,
OK_REDIRECT_TO_NON_SECURE_CONNECTION,
INVALID_MOVE_INTO_DESCENDANT,
INVALID_COPY_INTO_DESCENDANT,
PARTIAL_MOVE_DONE,
PARTIAL_COPY_DONE,
SHARE_WRONG_PARAMETER,
WRONG_SERVER_RESPONSE,
INVALID_CHARACTER_DETECT_IN_SERVER,
DELAYED_FOR_WIFI,
LOCAL_FILE_NOT_FOUND,
SERVICE_UNAVAILABLE,
SPECIFIC_SERVICE_UNAVAILABLE,
SPECIFIC_UNSUPPORTED_MEDIA_TYPE,
SPECIFIC_METHOD_NOT_ALLOWED
}
private boolean mSuccess = false; private boolean mSuccess = false;
private int mHttpCode = -1; private int mHttpCode = -1;
private String mHttpPhrase = null; private String mHttpPhrase = null;
@ -128,10 +70,9 @@ public class RemoteOperationResult<T extends Object>
private ArrayList<String> mAuthenticate = new ArrayList<>(); private ArrayList<String> mAuthenticate = new ArrayList<>();
private String mLastPermanentLocation = null; private String mLastPermanentLocation = null;
private T mData = null; private T mData = null;
/** /**
* Public constructor from result code. * Public constructor from result code.
* * <p>
* To be used when the caller takes the responsibility of interpreting the result of a {@link RemoteOperation} * To be used when the caller takes the responsibility of interpreting the result of a {@link RemoteOperation}
* *
* @param code {@link ResultCode} decided by the caller. * @param code {@link ResultCode} decided by the caller.
@ -146,6 +87,7 @@ public class RemoteOperationResult<T extends Object>
/** /**
* Create a new RemoteOperationResult based on the result given by a previous one. * Create a new RemoteOperationResult based on the result given by a previous one.
* It does not copy the data. * It does not copy the data.
*
* @param prevRemoteOperation * @param prevRemoteOperation
*/ */
public RemoteOperationResult(RemoteOperationResult prevRemoteOperation) { public RemoteOperationResult(RemoteOperationResult prevRemoteOperation) {
@ -161,9 +103,9 @@ public class RemoteOperationResult<T extends Object>
/** /**
* Public constructor from exception. * Public constructor from exception.
* * <p>
* To be used when an exception prevented the end of the {@link RemoteOperation}. * To be used when an exception prevented the end of the {@link RemoteOperation}.
* * <p>
* Determines a {@link ResultCode} depending on the type of the exception. * Determines a {@link ResultCode} depending on the type of the exception.
* *
* @param e Exception that interrupted the {@link RemoteOperation} * @param e Exception that interrupted the {@link RemoteOperation}
@ -193,7 +135,7 @@ public class RemoteOperationResult<T extends Object>
mCode = ResultCode.ACCOUNT_EXCEPTION; mCode = ResultCode.ACCOUNT_EXCEPTION;
} else if (e instanceof SSLException || e instanceof RuntimeException) { } else if (e instanceof SSLException || e instanceof RuntimeException) {
if(e instanceof SSLPeerUnverifiedException) { if (e instanceof SSLPeerUnverifiedException) {
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED; mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
} else { } else {
CertificateCombinedException se = getCertificateCombinedException(e); CertificateCombinedException se = getCertificateCombinedException(e);
@ -220,9 +162,9 @@ public class RemoteOperationResult<T extends Object>
/** /**
* Public constructor from separate elements of an HTTP or DAV response. * Public constructor from separate elements of an HTTP or DAV response.
* * <p>
* To be used when the result needs to be interpreted from the response of an HTTP/DAV method. * To be used when the result needs to be interpreted from the response of an HTTP/DAV method.
* * <p>
* Determines a {@link ResultCode} from the already executed method received as a parameter. Generally, * Determines a {@link ResultCode} from the already executed method received as a parameter. Generally,
* will depend on the HTTP code and HTTP response headers received. In some cases will inspect also the * will depend on the HTTP code and HTTP response headers received. In some cases will inspect also the
* response body * response body
@ -285,44 +227,18 @@ public class RemoteOperationResult<T extends Object>
} }
} }
/**
* Parse the error message included in the body response, if any, and set the specific result
* code
*
* @param bodyResponse okHttp response body
* @param resultCode our own custom result code
* @throws IOException
*/
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
if (bodyResponse != null && bodyResponse.length() > 0) {
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
ErrorMessageParser xmlParser = new ErrorMessageParser();
try {
String errorMessage = xmlParser.parseXMLResponse(is);
if (errorMessage != "" && errorMessage != null) {
mCode = resultCode;
mHttpPhrase = errorMessage;
}
} catch (Exception e) {
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
// mCode stays as set in this(success, httpCode, headers)
}
}
}
/** /**
* Public constructor from separate elements of an HTTP or DAV response. * Public constructor from separate elements of an HTTP or DAV response.
* * <p>
* To be used when the result needs to be interpreted from HTTP response elements that could come from * To be used when the result needs to be interpreted from HTTP response elements that could come from
* different requests (WARNING: black magic, try to avoid). * different requests (WARNING: black magic, try to avoid).
* * <p>
* * <p>
* Determines a {@link ResultCode} depending on the HTTP code and HTTP response headers received. * Determines a {@link ResultCode} depending on the HTTP code and HTTP response headers received.
* *
* @param httpCode HTTP status code returned by an HTTP/DAV method. * @param httpCode HTTP status code returned by an HTTP/DAV method.
* @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method * @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method
* @param headers HTTP response header returned by an HTTP/DAV method * @param headers HTTP response header returned by an HTTP/DAV method
*/ */
public RemoteOperationResult(int httpCode, String httpPhrase, Headers headers) { public RemoteOperationResult(int httpCode, String httpPhrase, Headers headers) {
this(httpCode, httpPhrase); this(httpCode, httpPhrase);
@ -345,7 +261,7 @@ public class RemoteOperationResult<T extends Object>
/** /**
* Private constructor for results built interpreting a HTTP or DAV response. * Private constructor for results built interpreting a HTTP or DAV response.
* * <p>
* Determines a {@link ResultCode} depending of the type of the exception. * Determines a {@link ResultCode} depending of the type of the exception.
* *
* @param httpCode HTTP status code returned by the HTTP/DAV method. * @param httpCode HTTP status code returned by the HTTP/DAV method.
@ -389,11 +305,40 @@ public class RemoteOperationResult<T extends Object>
} }
} }
/**
* Parse the error message included in the body response, if any, and set the specific result
* code
*
* @param bodyResponse okHttp response body
* @param resultCode our own custom result code
* @throws IOException
*/
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
if (bodyResponse != null && bodyResponse.length() > 0) {
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
ErrorMessageParser xmlParser = new ErrorMessageParser();
try {
String errorMessage = xmlParser.parseXMLResponse(is);
if (errorMessage != "" && errorMessage != null) {
mCode = resultCode;
mHttpPhrase = errorMessage;
}
} catch (Exception e) {
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
// mCode stays as set in this(success, httpCode, headers)
}
}
}
public boolean isSuccess() { public boolean isSuccess() {
return mSuccess; return mSuccess;
} }
public void setSuccess(boolean success) {
this.mSuccess = success;
}
public boolean isCancelled() { public boolean isCancelled() {
return mCode == ResultCode.CANCELLED; return mCode == ResultCode.CANCELLED;
} }
@ -459,10 +404,11 @@ public class RemoteOperationResult<T extends Object>
return "Unknown host exception"; return "Unknown host exception";
} else if (mException instanceof CertificateCombinedException) { } else if (mException instanceof CertificateCombinedException) {
if (((CertificateCombinedException) mException).isRecoverable()) if (((CertificateCombinedException) mException).isRecoverable()) {
return "SSL recoverable exception"; return "SSL recoverable exception";
else } else {
return "SSL exception"; return "SSL exception";
}
} else if (mException instanceof SSLException) { } else if (mException instanceof SSLException) {
return "SSL exception"; return "SSL exception";
@ -572,15 +518,65 @@ public class RemoteOperationResult<T extends Object>
mLastPermanentLocation = lastPermanentLocation; mLastPermanentLocation = lastPermanentLocation;
} }
public void setSuccess(boolean success) { public T getData() {
this.mSuccess = success; return mData;
} }
public void setData(T data) { public void setData(T data) {
mData = data; mData = data;
} }
public T getData() { public enum ResultCode {
return mData; OK,
OK_SSL,
OK_NO_SSL,
UNHANDLED_HTTP_CODE,
UNAUTHORIZED,
FILE_NOT_FOUND,
INSTANCE_NOT_CONFIGURED,
UNKNOWN_ERROR,
WRONG_CONNECTION,
TIMEOUT,
INCORRECT_ADDRESS,
HOST_NOT_AVAILABLE,
NO_NETWORK_CONNECTION,
SSL_ERROR,
SSL_RECOVERABLE_PEER_UNVERIFIED,
BAD_OC_VERSION,
CANCELLED,
INVALID_LOCAL_FILE_NAME,
INVALID_OVERWRITE,
CONFLICT,
OAUTH2_ERROR,
SYNC_CONFLICT,
LOCAL_STORAGE_FULL,
LOCAL_STORAGE_NOT_MOVED,
LOCAL_STORAGE_NOT_COPIED,
OAUTH2_ERROR_ACCESS_DENIED,
QUOTA_EXCEEDED,
ACCOUNT_NOT_FOUND,
ACCOUNT_EXCEPTION,
ACCOUNT_NOT_NEW,
ACCOUNT_NOT_THE_SAME,
INVALID_CHARACTER_IN_NAME,
SHARE_NOT_FOUND,
LOCAL_STORAGE_NOT_REMOVED,
FORBIDDEN,
SHARE_FORBIDDEN,
SPECIFIC_FORBIDDEN,
OK_REDIRECT_TO_NON_SECURE_CONNECTION,
INVALID_MOVE_INTO_DESCENDANT,
INVALID_COPY_INTO_DESCENDANT,
PARTIAL_MOVE_DONE,
PARTIAL_COPY_DONE,
SHARE_WRONG_PARAMETER,
WRONG_SERVER_RESPONSE,
INVALID_CHARACTER_DETECT_IN_SERVER,
DELAYED_FOR_WIFI,
LOCAL_FILE_NOT_FOUND,
SERVICE_UNAVAILABLE,
SPECIFIC_SERVICE_UNAVAILABLE,
SPECIFIC_UNSUPPORTED_MEDIA_TYPE,
SPECIFIC_METHOD_NOT_ALLOWED
} }
} }

View File

@ -39,7 +39,6 @@ public class RandomUtils {
/** /**
* @param length the number of random chars to be generated * @param length the number of random chars to be generated
*
* @return String containing random chars * @return String containing random chars
*/ */
public static String generateRandomString(int length) { public static String generateRandomString(int length) {
@ -59,7 +58,7 @@ public class RandomUtils {
*/ */
public static int generateRandomInteger(int min, int max) { public static int generateRandomInteger(int min, int max) {
Random r = new Random(); Random r = new Random();
return r.nextInt(max-min) + min; return r.nextInt(max - min) + min;
} }
/** /**

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -30,9 +30,9 @@ import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod; import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import java.net.URL; import java.net.URL;
@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* Remote operation moving a remote file or folder in the ownCloud server to a different folder * Remote operation moving a remote file or folder in the ownCloud server to a different folder
* in the same account. * in the same account.
* * <p>
* Allows renaming the moving file/folder at the same time. * Allows renaming the moving file/folder at the same time.
* *
* @author David A. Velasco * @author David A. Velasco
@ -112,14 +112,13 @@ public class CopyRemoteFileOperation extends RemoteOperation {
final int status = client.executeHttpMethod(copyMethod); final int status = client.executeHttpMethod(copyMethod);
if(status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT) { if (status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT) {
result = new RemoteOperationResult<>(ResultCode.OK); result = new RemoteOperationResult<>(ResultCode.OK);
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) { } else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE); result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
client.exhaustResponse(copyMethod.getResponseBodyAsStream()); client.exhaustResponse(copyMethod.getResponseBodyAsStream());
/// for other errors that could be explicitly handled, check first: /// for other errors that could be explicitly handled, check first:
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4 /// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,23 +24,21 @@
package com.owncloud.android.lib.resources.files; package com.owncloud.android.lib.resources.files;
import android.net.Uri; import android.net.Uri;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.webdav.MkColMethod; import com.owncloud.android.lib.common.http.methods.webdav.MkColMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.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;
import java.net.URL; import java.net.URL;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Remote operation performing the creation of a new folder in the ownCloud server. * Remote operation performing the creation of a new folder in the ownCloud server.
* *
@ -60,6 +58,7 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
/** /**
* Constructor * Constructor
*
* @param remotePath Full path to the new directory to create in the remote server. * @param remotePath Full path to the new directory to create in the remote server.
* @param createFullPath 'True' means that all the ancestor folders should be created. * @param createFullPath 'True' means that all the ancestor folders should be created.
*/ */
@ -79,12 +78,12 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
RemoteOperationResult result; RemoteOperationResult result;
OwnCloudVersion version = client.getOwnCloudVersion(); OwnCloudVersion version = client.getOwnCloudVersion();
boolean versionWithForbiddenChars = boolean versionWithForbiddenChars =
(version != null && version.isVersionWithForbiddenCharacters()); (version != null && version.isVersionWithForbiddenCharacters());
boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars); boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars);
if (noInvalidChars) { if (noInvalidChars) {
result = createFolder(client); result = createFolder(client);
if (!result.isSuccess() && mCreateFullPath && if (!result.isSuccess() && mCreateFullPath &&
RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) { RemoteOperationResult.ResultCode.CONFLICT == result.getCode()) {
result = createParentFolder(FileUtils.getParentPath(mRemotePath), client); result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
if (result.isSuccess()) { if (result.isSuccess()) {
result = createFolder(client); // second (and last) try result = createFolder(client); // second (and last) try

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -56,9 +56,8 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName(); private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName();
private static final int FORBIDDEN_ERROR = 403; private static final int FORBIDDEN_ERROR = 403;
private static final int SERVICE_UNAVAILABLE_ERROR = 503; private static final int SERVICE_UNAVAILABLE_ERROR = 503;
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
private long mModificationTimestamp = 0; private long mModificationTimestamp = 0;
private String mEtag = ""; private String mEtag = "";
private GetMethod mGet; private GetMethod mGet;
@ -83,18 +82,17 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
tmpFile.getParentFile().mkdirs(); tmpFile.getParentFile().mkdirs();
result = downloadFile(client, tmpFile); result = downloadFile(client, tmpFile);
Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
result.getLogMessage()); result.getLogMessage());
} catch (Exception e) { } catch (Exception e) {
result = new RemoteOperationResult<>(e); result = new RemoteOperationResult<>(e);
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
result.getLogMessage(), e); result.getLogMessage(), e);
} }
return result; return result;
} }
private RemoteOperationResult downloadFile(OwnCloudClient client, File targetFile) throws private RemoteOperationResult downloadFile(OwnCloudClient client, File targetFile) throws
Exception { Exception {
@ -118,8 +116,8 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
long totalToTransfer = long totalToTransfer =
(contentLength != null (contentLength != null
&& contentLength.length() > 0) && contentLength.length() > 0)
? Long.parseLong(contentLength) ? Long.parseLong(contentLength)
: 0; : 0;
byte[] bytes = new byte[4096]; byte[] bytes = new byte[4096];
int readResult; int readResult;
@ -136,7 +134,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
it = mDataTransferListeners.iterator(); it = mDataTransferListeners.iterator();
while (it.hasNext()) { while (it.hasNext()) {
it.next().onTransferProgress(readResult, transferred, totalToTransfer, it.next().onTransferProgress(readResult, transferred, totalToTransfer,
targetFile.getName()); targetFile.getName());
} }
} }
} }
@ -144,8 +142,8 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
savedFile = true; savedFile = true;
final String modificationTime = final String modificationTime =
mGet.getResponseHeaders().get("Last-Modified") != null mGet.getResponseHeaders().get("Last-Modified") != null
? mGet.getResponseHeaders().get("Last-Modified") ? mGet.getResponseHeaders().get("Last-Modified")
: mGet.getResponseHeader("last-modified"); : mGet.getResponseHeader("last-modified");
if (modificationTime != null) { if (modificationTime != null) {
final Date d = WebdavUtils.parseResponseDate(modificationTime); final Date d = WebdavUtils.parseResponseDate(modificationTime);
@ -177,8 +175,12 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
? new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK) ? new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK)
: new RemoteOperationResult<>(mGet); : new RemoteOperationResult<>(mGet);
} finally { } finally {
if (fos != null) fos.close(); if (fos != null) {
if (bis != null) bis.close(); fos.close();
}
if (bis != null) {
bis.close();
}
if (!savedFile && targetFile.exists()) { if (!savedFile && targetFile.exists()) {
targetFile.delete(); targetFile.delete();
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -30,55 +30,56 @@ import java.io.File;
public class FileUtils { public class FileUtils {
private static final String TAG = FileUtils.class.getSimpleName(); public static final String PATH_SEPARATOR = "/";
public static final String FINAL_CHUNKS_FILE = ".file";
private static final String TAG = FileUtils.class.getSimpleName();
public static final String PATH_SEPARATOR = "/"; public static String getParentPath(String remotePath) {
public static final String FINAL_CHUNKS_FILE = ".file"; String parentPath = new File(remotePath).getParent();
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
return parentPath;
}
public static String getParentPath(String remotePath) { /**
String parentPath = new File(remotePath).getParent(); * Validate the fileName to detect if contains any forbidden character: / , \ , < , > ,
parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR; * : , " , | , ? , *
return parentPath; *
} * @param fileName
* @param versionSupportsForbiddenChars
/** * @return
* Validate the fileName to detect if contains any forbidden character: / , \ , < , > , */
* : , " , | , ? , * public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
* @param fileName boolean result = true;
* @param versionSupportsForbiddenChars
* @return
*/
public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
boolean result = true;
Log_OC.d(TAG, "fileName =======" + fileName);
if ( (versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
(!versionSupportsForbiddenChars && ( fileName.contains(PATH_SEPARATOR) ||
fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
fileName.contains("?") || fileName.contains("*") ) ) ) {
result = false; Log_OC.d(TAG, "fileName =======" + fileName);
} if ((versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
return result; (!versionSupportsForbiddenChars && (fileName.contains(PATH_SEPARATOR) ||
} fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
/** fileName.contains("?") || fileName.contains("*")))) {
* Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | ,
* ? , * result = false;
* @param path }
* @return return result;
*/ }
public static boolean isValidPath(String path, boolean versionSupportsForbidenChars) {
boolean result = true; /**
* Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | ,
Log_OC.d(TAG, "path ....... " + path); * ? , *
if (!versionSupportsForbidenChars && *
(path.contains("\\") || path.contains("<") || path.contains(">") || * @param path
path.contains(":") || path.contains("\"") || path.contains("|") || * @return
path.contains("?") || path.contains("*") ) ){ */
result = false; public static boolean isValidPath(String path, boolean versionSupportsForbidenChars) {
} boolean result = true;
return result;
} Log_OC.d(TAG, "path ....... " + path);
if (!versionSupportsForbidenChars &&
(path.contains("\\") || path.contains("<") || path.contains(">") ||
path.contains(":") || path.contains("\"") || path.contains("|") ||
path.contains("?") || path.contains("*"))) {
result = false;
}
return result;
}
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -31,9 +31,9 @@ import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod; import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import java.net.URL; import java.net.URL;
@ -42,7 +42,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* Remote operation moving a remote file or folder in the ownCloud server to a different folder * Remote operation moving a remote file or folder in the ownCloud server to a different folder
* in the same account. * in the same account.
* * <p>
* Allows renaming the moving file/folder at the same time. * Allows renaming the moving file/folder at the same time.
* *
* @author David A. Velasco * @author David A. Velasco
@ -65,7 +65,7 @@ public class MoveRemoteFileOperation extends RemoteOperation {
/** /**
* Constructor. * Constructor.
* * <p>
* TODO Paths should finish in "/" in the case of folders. ? * TODO Paths should finish in "/" in the case of folders. ?
* *
* @param srcRemotePath Remote path of the file/folder to move. * @param srcRemotePath Remote path of the file/folder to move.
@ -90,7 +90,7 @@ public class MoveRemoteFileOperation extends RemoteOperation {
OwnCloudVersion version = client.getOwnCloudVersion(); OwnCloudVersion version = client.getOwnCloudVersion();
boolean versionWithForbiddenChars = boolean versionWithForbiddenChars =
(version != null && version.isVersionWithForbiddenCharacters()); (version != null && version.isVersionWithForbiddenCharacters());
/// check parameters /// check parameters
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) { if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
@ -115,7 +115,7 @@ public class MoveRemoteFileOperation extends RemoteOperation {
final MoveMethod move = new MoveMethod( final MoveMethod move = new MoveMethod(
new URL(srcWebDavUri + WebdavUtils.encodePath(mSrcRemotePath)), new URL(srcWebDavUri + WebdavUtils.encodePath(mSrcRemotePath)),
client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath), client.getUserFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath),
mOverwrite); mOverwrite);
if (moveChunkedFile) { if (moveChunkedFile) {
@ -128,7 +128,7 @@ public class MoveRemoteFileOperation extends RemoteOperation {
final int status = client.executeHttpMethod(move); final int status = client.executeHttpMethod(move);
/// process response /// process response
if(isSuccess(status)) { if (isSuccess(status)) {
result = new RemoteOperationResult<>(ResultCode.OK); result = new RemoteOperationResult<>(ResultCode.OK);
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) { } else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
@ -144,12 +144,12 @@ public class MoveRemoteFileOperation extends RemoteOperation {
} }
Log.i(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + Log.i(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
result.getLogMessage()); result.getLogMessage());
} catch (Exception e) { } catch (Exception e) {
result = new RemoteOperationResult<>(e); result = new RemoteOperationResult<>(e);
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
result.getLogMessage(), e); result.getLogMessage(), e);
} }
return result; return result;

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -102,7 +102,7 @@ public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
result = new RemoteOperationResult<>(e); result = new RemoteOperationResult<>(e);
e.printStackTrace(); e.printStackTrace();
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(), Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
result.getException()); result.getException());
} }
return result; return result;

View File

@ -24,6 +24,7 @@
package com.owncloud.android.lib.resources.files; package com.owncloud.android.lib.resources.files;
import at.bitfire.dav4android.Response;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
@ -38,8 +39,6 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import at.bitfire.dav4android.Response;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/** /**
@ -103,7 +102,7 @@ public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteF
result.setData(mFolderAndFiles); result.setData(mFolderAndFiles);
} else { // synchronization failed } else { // synchronization failed
result = new RemoteOperationResult<> (propfindMethod); result = new RemoteOperationResult<>(propfindMethod);
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -28,10 +28,6 @@ import android.net.Uri;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import at.bitfire.dav4android.Property; import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.Response; import at.bitfire.dav4android.Response;
import at.bitfire.dav4android.property.CreationDate; import at.bitfire.dav4android.property.CreationDate;
@ -47,6 +43,10 @@ import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
import at.bitfire.dav4android.property.owncloud.OCSize; import at.bitfire.dav4android.property.owncloud.OCSize;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0; import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4_0;
/** /**
@ -58,11 +58,24 @@ import static com.owncloud.android.lib.common.OwnCloudClient.WEBDAV_FILES_PATH_4
public class RemoteFile implements Parcelable, Serializable { public class RemoteFile implements Parcelable, Serializable {
/**
* Parcelable Methods
*/
public static final Parcelable.Creator<RemoteFile> CREATOR = new Parcelable.Creator<RemoteFile>() {
@Override
public RemoteFile createFromParcel(Parcel source) {
return new RemoteFile(source);
}
@Override
public RemoteFile[] newArray(int size) {
return new RemoteFile[size];
}
};
/** /**
* Generated - should be refreshed every time the class changes!! * Generated - should be refreshed every time the class changes!!
*/ */
private static final long serialVersionUID = -8965995357413958539L; private static final long serialVersionUID = -8965995357413958539L;
private String mRemotePath; private String mRemotePath;
private String mMimeType; private String mMimeType;
private long mLength; private long mLength;
@ -76,6 +89,100 @@ public class RemoteFile implements Parcelable, Serializable {
private BigDecimal mQuotaAvailableBytes; private BigDecimal mQuotaAvailableBytes;
private String mPrivateLink; private String mPrivateLink;
public RemoteFile() {
resetData();
}
/**
* Create new {@link RemoteFile} with given path.
* <p>
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
*
* @param path The remote path of the file.
*/
public RemoteFile(String path) {
resetData();
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) {
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
}
mRemotePath = path;
mCreationTimestamp = 0;
mLength = 0;
mMimeType = "DIR";
mQuotaUsedBytes = BigDecimal.ZERO;
mQuotaAvailableBytes = BigDecimal.ZERO;
mPrivateLink = null;
}
public RemoteFile(final Response davResource, String userId) {
this(getRemotePathFromUrl(davResource.getHref(), userId));
final List<Property> properties = davResource.getProperties();
for (Property property : properties) {
if (property instanceof CreationDate) {
this.setCreationTimestamp(
Long.parseLong(((CreationDate) property).getCreationDate()));
}
if (property instanceof GetContentLength) {
this.setLength(((GetContentLength) property).getContentLength());
}
if (property instanceof GetContentType) {
this.setMimeType(((GetContentType) property).getType());
}
if (property instanceof GetLastModified) {
this.setModifiedTimestamp(((GetLastModified) property).getLastModified());
}
if (property instanceof GetETag) {
this.setEtag(((GetETag) property).getETag());
}
if (property instanceof OCPermissions) {
this.setPermissions(((OCPermissions) property).getPermission());
}
if (property instanceof OCId) {
this.setRemoteId(((OCId) property).getId());
}
if (property instanceof OCSize) {
this.setSize(((OCSize) property).getSize());
}
if (property instanceof QuotaUsedBytes) {
this.setQuotaUsedBytes(
BigDecimal.valueOf(((QuotaUsedBytes) property).getQuotaUsedBytes()));
}
if (property instanceof QuotaAvailableBytes) {
this.setQuotaAvailableBytes(
BigDecimal.valueOf(((QuotaAvailableBytes) property).getQuotaAvailableBytes()));
}
if (property instanceof OCPrivatelink) {
this.setPrivateLink(((OCPrivatelink) property).getLink());
}
}
}
/**
* Reconstruct from parcel
*
* @param source The source parcel
*/
protected RemoteFile(Parcel source) {
readFromParcel(source);
}
/**
* Retrieves a relative path from a remote file url
* <p>
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
*
* @param url remote file url
* @param userId file owner
* @return remote relative path of the file
*/
private static String getRemotePathFromUrl(HttpUrl url, String userId) {
final String davFilesPath = WEBDAV_FILES_PATH_4_0 + userId;
final String absoluteDavPath = Uri.decode(url.encodedPath());
final String pathToOc = absoluteDavPath.split(davFilesPath)[0];
return absoluteDavPath.replace(pathToOc + davFilesPath, "");
}
/** /**
* Getters and Setters * Getters and Setters
*/ */
@ -168,80 +275,6 @@ public class RemoteFile implements Parcelable, Serializable {
mPrivateLink = privateLink; mPrivateLink = privateLink;
} }
public RemoteFile() {
resetData();
}
/**
* Create new {@link RemoteFile} with given path.
*
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
*
* @param path The remote path of the file.
*/
public RemoteFile(String path) {
resetData();
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) {
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
}
mRemotePath = path;
mCreationTimestamp = 0;
mLength = 0;
mMimeType = "DIR";
mQuotaUsedBytes = BigDecimal.ZERO;
mQuotaAvailableBytes = BigDecimal.ZERO;
mPrivateLink = null;
}
public RemoteFile(final Response davResource, String userId) {
this(getRemotePathFromUrl(davResource.getHref(), userId));
final List<Property> properties = davResource.getProperties();
for(Property property : properties) {
if(property instanceof CreationDate)
this.setCreationTimestamp(
Long.parseLong(((CreationDate) property).getCreationDate()));
if(property instanceof GetContentLength)
this.setLength(((GetContentLength) property).getContentLength());
if(property instanceof GetContentType)
this.setMimeType(((GetContentType) property).getType());
if(property instanceof GetLastModified)
this.setModifiedTimestamp(((GetLastModified) property).getLastModified());
if(property instanceof GetETag)
this.setEtag(((GetETag) property).getETag());
if(property instanceof OCPermissions)
this.setPermissions(((OCPermissions) property).getPermission());
if(property instanceof OCId)
this.setRemoteId(((OCId) property).getId());
if(property instanceof OCSize)
this.setSize(((OCSize) property).getSize());
if(property instanceof QuotaUsedBytes)
this.setQuotaUsedBytes(
BigDecimal.valueOf(((QuotaUsedBytes) property).getQuotaUsedBytes()));
if(property instanceof QuotaAvailableBytes)
this.setQuotaAvailableBytes(
BigDecimal.valueOf(((QuotaAvailableBytes) property).getQuotaAvailableBytes()));
if(property instanceof OCPrivatelink)
this.setPrivateLink(((OCPrivatelink) property).getLink());
}
}
/**
* Retrieves a relative path from a remote file url
*
* Example: url:port/remote.php/dav/files/username/Documents/text.txt => /Documents/text.txt
*
* @param url remote file url
* @param userId file owner
* @return remote relative path of the file
*/
private static String getRemotePathFromUrl(HttpUrl url, String userId) {
final String davFilesPath = WEBDAV_FILES_PATH_4_0 + userId;
final String absoluteDavPath = Uri.decode(url.encodedPath());
final String pathToOc = absoluteDavPath.split(davFilesPath)[0];
return absoluteDavPath.replace(pathToOc + davFilesPath, "");
}
/** /**
* Used internally. Reset all file properties * Used internally. Reset all file properties
*/ */
@ -260,31 +293,6 @@ public class RemoteFile implements Parcelable, Serializable {
mPrivateLink = null; mPrivateLink = null;
} }
/**
* Parcelable Methods
*/
public static final Parcelable.Creator<RemoteFile> CREATOR = new Parcelable.Creator<RemoteFile>() {
@Override
public RemoteFile createFromParcel(Parcel source) {
return new RemoteFile(source);
}
@Override
public RemoteFile[] newArray(int size) {
return new RemoteFile[size];
}
};
/**
* Reconstruct from parcel
*
* @param source The source parcel
*/
protected RemoteFile(Parcel source) {
readFromParcel(source);
}
public void readFromParcel(Parcel source) { public void readFromParcel(Parcel source) {
mRemotePath = source.readString(); mRemotePath = source.readString();
mMimeType = source.readString(); mMimeType = source.readString();

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,20 +24,19 @@
package com.owncloud.android.lib.resources.files; package com.owncloud.android.lib.resources.files;
import java.io.File;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod; import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.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;
import java.io.File;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/** /**
* Remote operation performing the rename of a remote file or folder in the ownCloud server. * Remote operation performing the rename of a remote file or folder in the ownCloud server.
@ -73,7 +72,7 @@ public class RenameRemoteFileOperation extends RemoteOperation {
String parent = (new File(mOldRemotePath)).getParent(); String parent = (new File(mOldRemotePath)).getParent();
parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent + parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent +
FileUtils.PATH_SEPARATOR; FileUtils.PATH_SEPARATOR;
mNewRemotePath = parent + mNewName; mNewRemotePath = parent + mNewName;
if (isFolder) { if (isFolder) {
mNewRemotePath += FileUtils.PATH_SEPARATOR; mNewRemotePath += FileUtils.PATH_SEPARATOR;
@ -90,10 +89,11 @@ public class RenameRemoteFileOperation extends RemoteOperation {
final OwnCloudVersion version = client.getOwnCloudVersion(); final OwnCloudVersion version = client.getOwnCloudVersion();
final boolean versionWithForbiddenChars = final boolean versionWithForbiddenChars =
(version != null && version.isVersionWithForbiddenCharacters()); (version != null && version.isVersionWithForbiddenCharacters());
if(!FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars)) if (!FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars)) {
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME); return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
}
try { try {
if (mNewName.equals(mOldName)) { if (mNewName.equals(mOldName)) {
@ -134,11 +134,11 @@ public class RenameRemoteFileOperation extends RemoteOperation {
/** /**
* Checks if a file with the new name already exists. * Checks if a file with the new name already exists.
* *
* @return 'True' if the target path is already used by an existing file. * @return 'True' if the target path is already used by an existing file.
*/ */
private boolean targetPathIsUsed(OwnCloudClient client) { private boolean targetPathIsUsed(OwnCloudClient client) {
ExistenceCheckRemoteOperation existenceCheckRemoteOperation = ExistenceCheckRemoteOperation existenceCheckRemoteOperation =
new ExistenceCheckRemoteOperation(mNewRemotePath, false, false); new ExistenceCheckRemoteOperation(mNewRemotePath, false, false);
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client); RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
return exists.isSuccess(); return exists.isSuccess();
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -34,6 +34,7 @@ import com.owncloud.android.lib.common.operations.OperationCancelledException;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.MediaType;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
@ -41,13 +42,11 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import okhttp3.MediaType;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/** /**
* Remote operation performing the upload of a remote file to the ownCloud server. * Remote operation performing the upload of a remote file to the ownCloud server.
* *
* @author David A. Velasco * @author David A. Velasco
* @author masensio * @author masensio
* @author David González Verdugo * @author David González Verdugo
@ -56,15 +55,13 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
public class UploadRemoteFileOperation extends RemoteOperation { public class UploadRemoteFileOperation extends RemoteOperation {
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName(); private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
protected String mLocalPath; protected String mLocalPath;
protected String mRemotePath; protected String mRemotePath;
protected String mMimeType; protected String mMimeType;
protected String mFileLastModifTimestamp; protected String mFileLastModifTimestamp;
protected PutMethod mPutMethod = null; protected PutMethod mPutMethod = null;
protected String mRequiredEtag = null; protected String mRequiredEtag = null;
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>(); protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
protected FileRequestBody mFileRequestBody = null; protected FileRequestBody mFileRequestBody = null;
@ -153,8 +150,8 @@ public class UploadRemoteFileOperation extends RemoteOperation {
public Set<OnDatatransferProgressListener> getDataTransferListeners() { public Set<OnDatatransferProgressListener> getDataTransferListeners() {
return mDataTransferListeners; return mDataTransferListeners;
} }
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) { synchronized (mDataTransferListeners) {
mDataTransferListeners.add(listener); mDataTransferListeners.add(listener);
} }
@ -162,7 +159,7 @@ public class UploadRemoteFileOperation extends RemoteOperation {
mFileRequestBody.addDatatransferProgressListener(listener); mFileRequestBody.addDatatransferProgressListener(listener);
} }
} }
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) { synchronized (mDataTransferListeners) {
mDataTransferListeners.remove(listener); mDataTransferListeners.remove(listener);
@ -171,12 +168,13 @@ public class UploadRemoteFileOperation extends RemoteOperation {
mFileRequestBody.removeDatatransferProgressListener(listener); mFileRequestBody.removeDatatransferProgressListener(listener);
} }
} }
public void cancel() { public void cancel() {
synchronized (mCancellationRequested) { synchronized (mCancellationRequested) {
mCancellationRequested.set(true); mCancellationRequested.set(true);
if (mPutMethod != null) if (mPutMethod != null) {
mPutMethod.abort(); mPutMethod.abort();
}
} }
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -32,6 +32,7 @@ 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.files.FileUtils; import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation; import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
import okhttp3.MediaType;
import java.io.File; import java.io.File;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@ -39,8 +40,6 @@ import java.net.URL;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import okhttp3.MediaType;
import static com.owncloud.android.lib.common.http.HttpConstants.IF_MATCH_HEADER; import static com.owncloud.android.lib.common.http.HttpConstants.IF_MATCH_HEADER;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
@ -52,8 +51,8 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
*/ */
public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation { public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation {
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
public static final long CHUNK_SIZE = 1024000; public static final long CHUNK_SIZE = 1024000;
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName(); private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
private String mTransferId; private String mTransferId;
@ -127,11 +126,13 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
} }
} }
if (channel != null) if (channel != null) {
channel.close(); channel.close();
}
if (raf != null) if (raf != null) {
raf.close(); raf.close();
}
return result; return result;
} }

View File

@ -35,8 +35,8 @@ public class CreateRemoteChunkFolderOperation extends CreateRemoteFolderOperatio
/** /**
* Constructor * Constructor
* *
* @param remotePath Full path to the new directory to create in the remote server. * @param remotePath Full path to the new directory to create in the remote server.
* @param createFullPath 'True' means that all the ancestor folders should be created. * @param createFullPath 'True' means that all the ancestor folders should be created.
*/ */
public CreateRemoteChunkFolderOperation(String remotePath, boolean createFullPath) { public CreateRemoteChunkFolderOperation(String remotePath, boolean createFullPath) {
super(remotePath, createFullPath); super(remotePath, createFullPath);

View File

@ -35,6 +35,7 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.FormBody;
import java.net.URL; import java.net.URL;
import java.text.DateFormat; import java.text.DateFormat;
@ -42,8 +43,6 @@ import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import okhttp3.FormBody;
/** /**
* Creates a new share. This allows sharing with a user or group or as a link. * Creates a new share. This allows sharing with a user or group or as a link.
* *
@ -133,12 +132,11 @@ public class CreateRemoteShareOperation extends RemoteOperation {
mGetShareDetails = false; // defaults to false for backwards compatibility mGetShareDetails = false; // defaults to false for backwards compatibility
} }
/** /**
* Set name to create in Share resource. Ignored by servers previous to version 10.0.0 * Set name to create in Share resource. Ignored by servers previous to version 10.0.0
* *
* @param name Name to set to the target share. * @param name Name to set to the target share.
* Null or empty string result in no value set for the name. * Null or empty string result in no value set for the name.
*/ */
public void setName(String name) { public void setName(String name) {
this.mName = (name == null) ? "" : name; this.mName = (name == null) ? "" : name;
@ -154,7 +152,6 @@ public class CreateRemoteShareOperation extends RemoteOperation {
mPassword = password; mPassword = password;
} }
/** /**
* Set expiration date to create in Share resource. * Set expiration date to create in Share resource.
* *
@ -165,7 +162,6 @@ public class CreateRemoteShareOperation extends RemoteOperation {
mExpirationDateInMillis = expirationDateInMillis; mExpirationDateInMillis = expirationDateInMillis;
} }
/** /**
* Set permissions to create in Share resource. * Set permissions to create in Share resource.
* *

View File

@ -50,7 +50,6 @@ public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult>
private long mRemoteId; private long mRemoteId;
public GetRemoteShareOperation(long remoteId) { public GetRemoteShareOperation(long remoteId) {
mRemoteId = remoteId; mRemoteId = remoteId;
} }

View File

@ -36,7 +36,6 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@ -47,24 +46,24 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
/** /**
* Created by masensio on 08/10/2015. * Created by masensio on 08/10/2015.
* * <p>
* Retrieves a list of sharees (possible targets of a share) from the ownCloud server. * Retrieves a list of sharees (possible targets of a share) from the ownCloud server.
* * <p>
* Currently only handles users and groups. Users in other OC servers (federation) should be added later. * Currently only handles users and groups. Users in other OC servers (federation) should be added later.
* * <p>
* Depends on SHAREE API. {@See https://github.com/owncloud/documentation/issues/1626} * Depends on SHAREE API. {@See https://github.com/owncloud/documentation/issues/1626}
* * <p>
* Syntax: * Syntax:
* Entry point: ocs/v2.php/apps/files_sharing/api/v1/sharees * Entry point: ocs/v2.php/apps/files_sharing/api/v1/sharees
* HTTP method: GET * HTTP method: GET
* url argument: itemType - string, required * url argument: itemType - string, required
* url argument: format - string, optional * url argument: format - string, optional
* url argument: search - string, optional * url argument: search - string, optional
* url arguments: perPage - int, optional * url arguments: perPage - int, optional
* url arguments: page - int, optional * url arguments: page - int, optional
* * <p>
* Status codes: * Status codes:
* 100 - successful * 100 - successful
* *
* @author masensio * @author masensio
* @author David A. Velasco * @author David A. Velasco
@ -72,22 +71,22 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
*/ */
public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObject>> { public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObject>> {
public static final String NODE_VALUE = "value";
public static final String PROPERTY_LABEL = "label";
public static final String PROPERTY_SHARE_TYPE = "shareType";
public static final String PROPERTY_SHARE_WITH = "shareWith";
private static final String TAG = GetRemoteShareesOperation.class.getSimpleName(); private static final String TAG = GetRemoteShareesOperation.class.getSimpleName();
// OCS Routes // OCS Routes
private static final String OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees"; // from OC 8.2 private static final String OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees"; // from OC 8.2
// Arguments - names // Arguments - names
private static final String PARAM_FORMAT = "format"; private static final String PARAM_FORMAT = "format";
private static final String PARAM_ITEM_TYPE = "itemType"; private static final String PARAM_ITEM_TYPE = "itemType";
private static final String PARAM_SEARCH = "search"; private static final String PARAM_SEARCH = "search";
private static final String PARAM_PAGE = "page"; // default = 1 private static final String PARAM_PAGE = "page"; // default = 1
private static final String PARAM_PER_PAGE = "perPage"; // default = 200 private static final String PARAM_PER_PAGE = "perPage"; // default = 200
// Arguments - constant values // Arguments - constant values
private static final String VALUE_FORMAT = "json"; private static final String VALUE_FORMAT = "json";
private static final String VALUE_ITEM_TYPE = "file"; // to get the server search for users / groups private static final String VALUE_ITEM_TYPE = "file"; // to get the server search for users / groups
// JSON Node names // JSON Node names
private static final String NODE_OCS = "ocs"; private static final String NODE_OCS = "ocs";
private static final String NODE_DATA = "data"; private static final String NODE_DATA = "data";
@ -95,11 +94,6 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
private static final String NODE_USERS = "users"; private static final String NODE_USERS = "users";
private static final String NODE_GROUPS = "groups"; private static final String NODE_GROUPS = "groups";
private static final String NODE_REMOTES = "remotes"; private static final String NODE_REMOTES = "remotes";
public static final String NODE_VALUE = "value";
public static final String PROPERTY_LABEL = "label";
public static final String PROPERTY_SHARE_TYPE = "shareType";
public static final String PROPERTY_SHARE_WITH = "shareWith";
private String mSearchString; private String mSearchString;
private int mPage; private int mPage;
private int mPerPage; private int mPerPage;
@ -107,9 +101,9 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
/** /**
* Constructor * Constructor
* *
* @param searchString string for searching users, optional * @param searchString string for searching users, optional
* @param page page index in the list of results; beginning in 1 * @param page page index in the list of results; beginning in 1
* @param perPage maximum number of results in a single page * @param perPage maximum number of results in a single page
*/ */
public GetRemoteShareesOperation(String searchString, int page, int perPage) { public GetRemoteShareesOperation(String searchString, int page, int perPage) {
mSearchString = searchString; mSearchString = searchString;
@ -121,7 +115,7 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
protected RemoteOperationResult<ArrayList<JSONObject>> run(OwnCloudClient client) { protected RemoteOperationResult<ArrayList<JSONObject>> run(OwnCloudClient client) {
RemoteOperationResult<ArrayList<JSONObject>> result; RemoteOperationResult<ArrayList<JSONObject>> result;
try{ try {
Uri requestUri = client.getBaseUri(); Uri requestUri = client.getBaseUri();
Uri.Builder uriBuilder = requestUri.buildUpon() Uri.Builder uriBuilder = requestUri.buildUpon()
.appendEncodedPath(OCS_ROUTE) .appendEncodedPath(OCS_ROUTE)
@ -138,7 +132,7 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
int status = client.executeHttpMethod(getMethod); int status = client.executeHttpMethod(getMethod);
String response = getMethod.getResponseBodyAsString(); String response = getMethod.getResponseBodyAsString();
if(isSuccess(status)) { if (isSuccess(status)) {
Log_OC.d(TAG, "Successful response: " + response); Log_OC.d(TAG, "Successful response: " + response);
// Parse the response // Parse the response
@ -162,8 +156,8 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
}; };
ArrayList<JSONObject> data = new ArrayList<>(); // For result data ArrayList<JSONObject> data = new ArrayList<>(); // For result data
for (int i=0; i<6; i++) { for (int i = 0; i < 6; i++) {
for(int j=0; j< jsonResults[i].length(); j++){ for (int j = 0; j < jsonResults[i].length(); j++) {
JSONObject jsonResult = jsonResults[i].getJSONObject(j); JSONObject jsonResult = jsonResults[i].getJSONObject(j);
data.add(jsonResult); data.add(jsonResult);
Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL)); Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL));
@ -173,7 +167,7 @@ public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObj
result = new RemoteOperationResult<>(OK); result = new RemoteOperationResult<>(OK);
result.setData(data); result.setData(data);
Log_OC.d(TAG, "*** Get Users or groups completed " ); Log_OC.d(TAG, "*** Get Users or groups completed ");
} else { } else {
result = new RemoteOperationResult<>(getMethod); result = new RemoteOperationResult<>(getMethod);

View File

@ -98,7 +98,7 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation<ShareParser
if (isSuccess(status)) { if (isSuccess(status)) {
// Parse xml response and obtain the list of shares // Parse xml response and obtain the list of shares
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
new ShareXMLParser() new ShareXMLParser()
); );
parser.setOwnCloudVersion(client.getOwnCloudVersion()); parser.setOwnCloudVersion(client.getOwnCloudVersion());
parser.setServerBaseUri(client.getBaseUri()); parser.setServerBaseUri(client.getBaseUri());

View File

@ -69,7 +69,7 @@ public class GetRemoteSharesOperation extends RemoteOperation {
// Parse xml response and obtain the list of shares // Parse xml response and obtain the list of shares
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
new ShareXMLParser() new ShareXMLParser()
); );
parser.setOwnCloudVersion(client.getOwnCloudVersion()); parser.setOwnCloudVersion(client.getOwnCloudVersion());
parser.setServerBaseUri(client.getBaseUri()); parser.setServerBaseUri(client.getBaseUri());

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2017 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,15 +24,13 @@
package com.owncloud.android.lib.resources.shares; package com.owncloud.android.lib.resources.shares;
import java.io.File;
import java.io.Serializable;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.FileUtils;
import java.io.Serializable;
/** /**
* Contains the data of a Share from the Share API * Contains the data of a Share from the Share API
@ -42,13 +40,6 @@ import com.owncloud.android.lib.resources.files.FileUtils;
*/ */
public class OCShare implements Parcelable, Serializable { public class OCShare implements Parcelable, Serializable {
/**
* Generated - should be refreshed every time the class changes!!
*/
private static final long serialVersionUID = 4124975224281327921L;
private static final String TAG = OCShare.class.getSimpleName();
public static final int DEFAULT_PERMISSION = -1; public static final int DEFAULT_PERMISSION = -1;
public static final int READ_PERMISSION_FLAG = 1; public static final int READ_PERMISSION_FLAG = 1;
public static final int UPDATE_PERMISSION_FLAG = 2; public static final int UPDATE_PERMISSION_FLAG = 2;
@ -56,29 +47,47 @@ public class OCShare implements Parcelable, Serializable {
public static final int DELETE_PERMISSION_FLAG = 8; public static final int DELETE_PERMISSION_FLAG = 8;
public static final int SHARE_PERMISSION_FLAG = 16; public static final int SHARE_PERMISSION_FLAG = 16;
public static final int MAXIMUM_PERMISSIONS_FOR_FILE = public static final int MAXIMUM_PERMISSIONS_FOR_FILE =
READ_PERMISSION_FLAG + READ_PERMISSION_FLAG +
UPDATE_PERMISSION_FLAG + UPDATE_PERMISSION_FLAG +
SHARE_PERMISSION_FLAG; SHARE_PERMISSION_FLAG;
public static final int MAXIMUM_PERMISSIONS_FOR_FOLDER = public static final int MAXIMUM_PERMISSIONS_FOR_FOLDER =
MAXIMUM_PERMISSIONS_FOR_FILE + MAXIMUM_PERMISSIONS_FOR_FILE +
CREATE_PERMISSION_FLAG + CREATE_PERMISSION_FLAG +
DELETE_PERMISSION_FLAG; DELETE_PERMISSION_FLAG;
public static final int FEDERATED_PERMISSIONS_FOR_FILE_UP_TO_OC9 = public static final int FEDERATED_PERMISSIONS_FOR_FILE_UP_TO_OC9 =
READ_PERMISSION_FLAG + READ_PERMISSION_FLAG +
UPDATE_PERMISSION_FLAG; UPDATE_PERMISSION_FLAG;
public static final int FEDERATED_PERMISSIONS_FOR_FILE_AFTER_OC9 = public static final int FEDERATED_PERMISSIONS_FOR_FILE_AFTER_OC9 =
READ_PERMISSION_FLAG + READ_PERMISSION_FLAG +
UPDATE_PERMISSION_FLAG + UPDATE_PERMISSION_FLAG +
SHARE_PERMISSION_FLAG; SHARE_PERMISSION_FLAG;
public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 = public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 =
READ_PERMISSION_FLAG + READ_PERMISSION_FLAG +
UPDATE_PERMISSION_FLAG + UPDATE_PERMISSION_FLAG +
CREATE_PERMISSION_FLAG + CREATE_PERMISSION_FLAG +
DELETE_PERMISSION_FLAG; DELETE_PERMISSION_FLAG;
public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9 = public static final int FEDERATED_PERMISSIONS_FOR_FOLDER_AFTER_OC9 =
FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 + FEDERATED_PERMISSIONS_FOR_FOLDER_UP_TO_OC9 +
SHARE_PERMISSION_FLAG; SHARE_PERMISSION_FLAG;
/**
* Parcelable Methods
*/
public static final Parcelable.Creator<OCShare> CREATOR = new Parcelable.Creator<OCShare>() {
@Override
public OCShare createFromParcel(Parcel source) {
return new OCShare(source);
}
@Override
public OCShare[] newArray(int size) {
return new OCShare[size];
}
};
/**
* Generated - should be refreshed every time the class changes!!
*/
private static final long serialVersionUID = 4124975224281327921L;
private static final String TAG = OCShare.class.getSimpleName();
private long mId; private long mId;
private long mFileSource; private long mFileSource;
private long mItemSource; private long mItemSource;
@ -110,6 +119,17 @@ public class OCShare implements Parcelable, Serializable {
mPath = path; mPath = path;
} }
/// Getters and Setters
/**
* Reconstruct from parcel
*
* @param source The source parcel
*/
protected OCShare(Parcel source) {
readFromParcel(source);
}
/** /**
* Used internally. Reset all file properties * Used internally. Reset all file properties
*/ */
@ -132,8 +152,6 @@ public class OCShare implements Parcelable, Serializable {
mName = ""; mName = "";
} }
/// Getters and Setters
public long getId() { public long getId() {
return mId; return mId;
} }
@ -266,30 +284,6 @@ public class OCShare implements Parcelable, Serializable {
return ShareType.PUBLIC_LINK.equals(mShareType) && mShareWith.length() > 0; return ShareType.PUBLIC_LINK.equals(mShareType) && mShareWith.length() > 0;
} }
/**
* Parcelable Methods
*/
public static final Parcelable.Creator<OCShare> CREATOR = new Parcelable.Creator<OCShare>() {
@Override
public OCShare createFromParcel(Parcel source) {
return new OCShare(source);
}
@Override
public OCShare[] newArray(int size) {
return new OCShare[size];
}
};
/**
* Reconstruct from parcel
*
* @param source The source parcel
*/
protected OCShare(Parcel source) {
readFromParcel(source);
}
public void readFromParcel(Parcel source) { public void readFromParcel(Parcel source) {
mId = source.readLong(); mId = source.readLong();
@ -314,13 +308,11 @@ public class OCShare implements Parcelable, Serializable {
mName = source.readString(); mName = source.readString();
} }
@Override @Override
public int describeContents() { public int describeContents() {
return this.hashCode(); return this.hashCode();
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mId); dest.writeLong(mId);

View File

@ -25,21 +25,22 @@
package com.owncloud.android.lib.resources.shares; package com.owncloud.android.lib.resources.shares;
/** /**
* Provides method to define a set of share permissions and calculate the appropiate * Provides method to define a set of share permissions and calculate the appropiate
* int value representing it. * int value representing it.
*/ */
public class SharePermissionsBuilder { public class SharePermissionsBuilder {
/** Set of permissions */ /**
* Set of permissions
*/
private int mPermissions = OCShare.READ_PERMISSION_FLAG; // READ is minimum permission private int mPermissions = OCShare.READ_PERMISSION_FLAG; // READ is minimum permission
/** /**
* Sets or clears permission to reshare a file or folder. * Sets or clears permission to reshare a file or folder.
* *
* @param enabled 'True' to set, 'false' to clear. * @param enabled 'True' to set, 'false' to clear.
* @return Instance to builder itself, to allow consecutive calls to setters * @return Instance to builder itself, to allow consecutive calls to setters
*/ */
public SharePermissionsBuilder setSharePermission(boolean enabled) { public SharePermissionsBuilder setSharePermission(boolean enabled) {
updatePermission(OCShare.SHARE_PERMISSION_FLAG, enabled); updatePermission(OCShare.SHARE_PERMISSION_FLAG, enabled);
@ -49,8 +50,8 @@ public class SharePermissionsBuilder {
/** /**
* Sets or clears permission to update a folder or folder. * Sets or clears permission to update a folder or folder.
* *
* @param enabled 'True' to set, 'false' to clear. * @param enabled 'True' to set, 'false' to clear.
* @return Instance to builder itself, to allow consecutive calls to setters * @return Instance to builder itself, to allow consecutive calls to setters
*/ */
public SharePermissionsBuilder setUpdatePermission(boolean enabled) { public SharePermissionsBuilder setUpdatePermission(boolean enabled) {
updatePermission(OCShare.UPDATE_PERMISSION_FLAG, enabled); updatePermission(OCShare.UPDATE_PERMISSION_FLAG, enabled);
@ -60,8 +61,8 @@ public class SharePermissionsBuilder {
/** /**
* Sets or clears permission to create files in share folder. * Sets or clears permission to create files in share folder.
* *
* @param enabled 'True' to set, 'false' to clear. * @param enabled 'True' to set, 'false' to clear.
* @return Instance to builder itself, to allow consecutive calls to setters * @return Instance to builder itself, to allow consecutive calls to setters
*/ */
public SharePermissionsBuilder setCreatePermission(boolean enabled) { public SharePermissionsBuilder setCreatePermission(boolean enabled) {
updatePermission(OCShare.CREATE_PERMISSION_FLAG, enabled); updatePermission(OCShare.CREATE_PERMISSION_FLAG, enabled);
@ -71,8 +72,8 @@ public class SharePermissionsBuilder {
/** /**
* Sets or clears permission to delete files in a shared folder. * Sets or clears permission to delete files in a shared folder.
* *
* @param enabled 'True' to set, 'false' to clear. * @param enabled 'True' to set, 'false' to clear.
* @return Instance to builder itself, to allow consecutive calls to setters * @return Instance to builder itself, to allow consecutive calls to setters
*/ */
public SharePermissionsBuilder setDeletePermission(boolean enabled) { public SharePermissionsBuilder setDeletePermission(boolean enabled) {
updatePermission(OCShare.DELETE_PERMISSION_FLAG, enabled); updatePermission(OCShare.DELETE_PERMISSION_FLAG, enabled);
@ -82,8 +83,8 @@ public class SharePermissionsBuilder {
/** /**
* Common code to update the value of the set of permissions. * Common code to update the value of the set of permissions.
* *
* @param permissionsFlag Flag for the permission to update. * @param permissionsFlag Flag for the permission to update.
* @param enable 'True' to set, 'false' to clear. * @param enable 'True' to set, 'false' to clear.
*/ */
private void updatePermission(int permissionsFlag, boolean enable) { private void updatePermission(int permissionsFlag, boolean enable) {
if (enable) { if (enable) {
@ -98,7 +99,7 @@ public class SharePermissionsBuilder {
/** /**
* 'Builds' the int value for the accumulated set of permissions. * 'Builds' the int value for the accumulated set of permissions.
* *
* @return An int value representing the accumulated set of permissions. * @return An int value representing the accumulated set of permissions.
*/ */
public int build() { public int build() {
return mPermissions; return mPermissions;

View File

@ -32,7 +32,6 @@ import android.net.Uri;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -50,7 +49,6 @@ public class ShareToRemoteOperationResultParser {
private OwnCloudVersion mOwnCloudVersion = null; private OwnCloudVersion mOwnCloudVersion = null;
private Uri mServerBaseUri = null; private Uri mServerBaseUri = null;
public ShareToRemoteOperationResultParser(ShareXMLParser shareXmlParser) { public ShareToRemoteOperationResultParser(ShareXMLParser shareXmlParser) {
mShareXmlParser = shareXmlParser; mShareXmlParser = shareXmlParser;
} }
@ -94,7 +92,7 @@ public class ShareToRemoteOperationResultParser {
// (needed for OC servers < 9.0.0, see ShareXMLParser.java#line256) // (needed for OC servers < 9.0.0, see ShareXMLParser.java#line256)
if (share.getShareType() == ShareType.PUBLIC_LINK if (share.getShareType() == ShareType.PUBLIC_LINK
&& (share.getShareLink() == null && (share.getShareLink() == null
|| share.getShareLink().length() <= 0) || share.getShareLink().length() <= 0)
&& share.getToken().length() > 0) { && share.getToken().length() > 0) {
if (mServerBaseUri != null) { if (mServerBaseUri != null) {
String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion); String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion);
@ -112,11 +110,11 @@ public class ShareToRemoteOperationResultParser {
Log_OC.e(TAG, "Successful status with no share in the response"); Log_OC.e(TAG, "Successful status with no share in the response");
} }
} else if (mShareXmlParser.isWrongParameter()){ } else if (mShareXmlParser.isWrongParameter()) {
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER); result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER);
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage())); result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
} else if (mShareXmlParser.isNotFound()){ } else if (mShareXmlParser.isNotFound()) {
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND); result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND);
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage())); result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -27,55 +27,51 @@ package com.owncloud.android.lib.resources.shares;
/** /**
* Enum for Share Type, with values: * Enum for Share Type, with values:
* -1 - No shared * -1 - No shared
* 0 - Shared by user * 0 - Shared by user
* 1 - Shared by group * 1 - Shared by group
* 3 - Shared by public link * 3 - Shared by public link
* 4 - Shared by e-mail * 4 - Shared by e-mail
* 5 - Shared by contact * 5 - Shared by contact
*
* @author masensio
* *
* @author masensio
*/ */
public enum ShareType { public enum ShareType {
NO_SHARED (-1), NO_SHARED(-1),
USER (0), USER(0),
GROUP (1), GROUP(1),
PUBLIC_LINK (3), PUBLIC_LINK(3),
EMAIL (4), EMAIL(4),
CONTACT (5), CONTACT(5),
FEDERATED (6); FEDERATED(6);
private int value; private int value;
private ShareType(int value) private ShareType(int value) {
{
this.value = value; this.value = value;
} }
public int getValue() { public static ShareType fromValue(int value) {
return value; switch (value) {
} case -1:
return NO_SHARED;
public static ShareType fromValue(int value) case 0:
{ return USER;
switch (value) case 1:
{ return GROUP;
case -1: case 3:
return NO_SHARED; return PUBLIC_LINK;
case 0: case 4:
return USER; return EMAIL;
case 1: case 5:
return GROUP; return CONTACT;
case 3: case 6:
return PUBLIC_LINK; return FEDERATED;
case 4:
return EMAIL;
case 5:
return CONTACT;
case 6:
return FEDERATED;
} }
return null; return null;
} }
public int getValue() {
return value;
}
}; };

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -28,23 +28,22 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
/** /**
* Contains Constants for Share Operation * Contains Constants for Share Operation
* *
* @author masensio * @author masensio
* @author David González Verdugo * @author David González Verdugo
*
*/ */
public class ShareUtils { public class ShareUtils {
// OCS Route // OCS Route
public static final String SHARING_API_PATH ="ocs/v2.php/apps/files_sharing/api/v1/shares"; public static final String SHARING_API_PATH = "ocs/v2.php/apps/files_sharing/api/v1/shares";
// String to build the link with the token of a share: // String to build the link with the token of a share:
public static final String SHARING_LINK_PATH_BEFORE_VERSION_8 = "/public.php?service=files&t="; public static final String SHARING_LINK_PATH_BEFORE_VERSION_8 = "/public.php?service=files&t=";
public static final String SHARING_LINK_PATH_AFTER_VERSION_8 = "/index.php/s/"; public static final String SHARING_LINK_PATH_AFTER_VERSION_8 = "/index.php/s/";
public static String getSharingLinkPath(OwnCloudVersion version){ public static String getSharingLinkPath(OwnCloudVersion version) {
if (version!= null && version.isAfter8Version()){ if (version != null && version.isAfter8Version()) {
return SHARING_LINK_PATH_AFTER_VERSION_8; return SHARING_LINK_PATH_AFTER_VERSION_8;
} else { } else {
return SHARING_LINK_PATH_BEFORE_VERSION_8; return SHARING_LINK_PATH_BEFORE_VERSION_8;

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -24,417 +24,425 @@
package com.owncloud.android.lib.resources.shares; package com.owncloud.android.lib.resources.shares;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
//import android.util.Log;
import android.util.Xml; import android.util.Xml;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.FileUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
//import android.util.Log;
/** /**
* Parser for Share API Response * Parser for Share API Response
*
* @author masensio * @author masensio
* @author David González Verdugo * @author David González Verdugo
*/ */
public class ShareXMLParser { public class ShareXMLParser {
//private static final String TAG = ShareXMLParser.class.getSimpleName(); //private static final String TAG = ShareXMLParser.class.getSimpleName();
// No namespaces // No namespaces
private static final String ns = null; private static final String ns = null;
// NODES for XML Parser // NODES for XML Parser
private static final String NODE_OCS = "ocs"; private static final String NODE_OCS = "ocs";
private static final String NODE_META = "meta"; private static final String NODE_META = "meta";
private static final String NODE_STATUS = "status"; private static final String NODE_STATUS = "status";
private static final String NODE_STATUS_CODE = "statuscode"; private static final String NODE_STATUS_CODE = "statuscode";
private static final String NODE_MESSAGE = "message"; private static final String NODE_MESSAGE = "message";
private static final String NODE_DATA = "data"; private static final String NODE_DATA = "data";
private static final String NODE_ELEMENT = "element"; private static final String NODE_ELEMENT = "element";
private static final String NODE_ID = "id"; private static final String NODE_ID = "id";
private static final String NODE_ITEM_TYPE = "item_type"; private static final String NODE_ITEM_TYPE = "item_type";
private static final String NODE_ITEM_SOURCE = "item_source"; private static final String NODE_ITEM_SOURCE = "item_source";
private static final String NODE_PARENT = "parent"; private static final String NODE_PARENT = "parent";
private static final String NODE_SHARE_TYPE = "share_type"; private static final String NODE_SHARE_TYPE = "share_type";
private static final String NODE_SHARE_WITH = "share_with"; private static final String NODE_SHARE_WITH = "share_with";
private static final String NODE_FILE_SOURCE = "file_source"; private static final String NODE_FILE_SOURCE = "file_source";
private static final String NODE_PATH = "path"; private static final String NODE_PATH = "path";
private static final String NODE_PERMISSIONS = "permissions"; private static final String NODE_PERMISSIONS = "permissions";
private static final String NODE_STIME = "stime"; private static final String NODE_STIME = "stime";
private static final String NODE_EXPIRATION = "expiration"; private static final String NODE_EXPIRATION = "expiration";
private static final String NODE_TOKEN = "token"; private static final String NODE_TOKEN = "token";
private static final String NODE_STORAGE = "storage"; private static final String NODE_STORAGE = "storage";
private static final String NODE_MAIL_SEND = "mail_send"; private static final String NODE_MAIL_SEND = "mail_send";
private static final String NODE_SHARE_WITH_DISPLAY_NAME = "share_with_displayname"; private static final String NODE_SHARE_WITH_DISPLAY_NAME = "share_with_displayname";
private static final String NODE_NAME = "name"; private static final String NODE_NAME = "name";
private static final String NODE_URL = "url";
private static final String TYPE_FOLDER = "folder"; private static final String NODE_URL = "url";
private static final int SUCCESS = 200;
private static final int ERROR_WRONG_PARAMETER = 400;
private static final int ERROR_FORBIDDEN = 403;
private static final int ERROR_NOT_FOUND = 404;
private String mStatus; private static final String TYPE_FOLDER = "folder";
private int mStatusCode;
private String mMessage;
// Getters and Setters private static final int SUCCESS = 200;
public String getStatus() { private static final int ERROR_WRONG_PARAMETER = 400;
return mStatus; private static final int ERROR_FORBIDDEN = 403;
} private static final int ERROR_NOT_FOUND = 404;
public void setStatus(String status) { private String mStatus;
this.mStatus = status; private int mStatusCode;
} private String mMessage;
public int getStatusCode() { // Constructor
return mStatusCode; public ShareXMLParser() {
} mStatusCode = -1;
}
public void setStatusCode(int statusCode) { // Getters and Setters
this.mStatusCode = statusCode; public String getStatus() {
} return mStatus;
}
public String getMessage() { public void setStatus(String status) {
return mMessage; this.mStatus = status;
} }
public void setMessage(String message) { public int getStatusCode() {
this.mMessage = message; return mStatusCode;
} }
// Constructor public void setStatusCode(int statusCode) {
public ShareXMLParser() { this.mStatusCode = statusCode;
mStatusCode = -1; }
}
public boolean isSuccess() { public String getMessage() {
return mStatusCode == SUCCESS; return mMessage;
} }
public boolean isForbidden() { public void setMessage(String message) {
return mStatusCode == ERROR_FORBIDDEN; this.mMessage = message;
} }
public boolean isNotFound() { public boolean isSuccess() {
return mStatusCode == ERROR_NOT_FOUND; return mStatusCode == SUCCESS;
} }
public boolean isWrongParameter() { public boolean isForbidden() {
return mStatusCode == ERROR_WRONG_PARAMETER; return mStatusCode == ERROR_FORBIDDEN;
} }
/** public boolean isNotFound() {
* Parse is as response of Share API return mStatusCode == ERROR_NOT_FOUND;
* @param is }
* @return List of ShareRemoteFiles
* @throws XmlPullParserException
* @throws IOException
*/
public ArrayList<OCShare> parseXMLResponse(InputStream is) throws XmlPullParserException,
IOException {
try { public boolean isWrongParameter() {
// XMLPullParser return mStatusCode == ERROR_WRONG_PARAMETER;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); }
factory.setNamespaceAware(true);
XmlPullParser parser = Xml.newPullParser(); /**
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); * Parse is as response of Share API
parser.setInput(is, null); *
parser.nextTag(); * @param is
return readOCS(parser); * @return List of ShareRemoteFiles
* @throws XmlPullParserException
* @throws IOException
*/
public ArrayList<OCShare> parseXMLResponse(InputStream is) throws XmlPullParserException,
IOException {
} finally { try {
is.close(); // XMLPullParser
} XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
} factory.setNamespaceAware(true);
/** XmlPullParser parser = Xml.newPullParser();
* Parse OCS node parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
* @param parser parser.setInput(is, null);
* @return List of ShareRemoteFiles parser.nextTag();
* @throws XmlPullParserException return readOCS(parser);
* @throws IOException
*/
private ArrayList<OCShare> readOCS (XmlPullParser parser) throws XmlPullParserException,
IOException {
ArrayList<OCShare> shares = new ArrayList<>();
parser.require(XmlPullParser.START_TAG, ns , NODE_OCS);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// read NODE_META and NODE_DATA
if (name.equalsIgnoreCase(NODE_META)) {
readMeta(parser);
} else if (name.equalsIgnoreCase(NODE_DATA)) {
shares = readData(parser);
} else {
skip(parser);
}
} } finally {
return shares; is.close();
} }
}
/** /**
* Parse Meta node * Parse OCS node
* @param parser *
* @throws XmlPullParserException * @param parser
* @throws IOException * @return List of ShareRemoteFiles
*/ * @throws XmlPullParserException
private void readMeta(XmlPullParser parser) throws XmlPullParserException, IOException { * @throws IOException
parser.require(XmlPullParser.START_TAG, ns, NODE_META); */
//Log_OC.d(TAG, "---- NODE META ---"); private ArrayList<OCShare> readOCS(XmlPullParser parser) throws XmlPullParserException,
while (parser.next() != XmlPullParser.END_TAG) { IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) { ArrayList<OCShare> shares = new ArrayList<>();
continue; parser.require(XmlPullParser.START_TAG, ns, NODE_OCS);
} while (parser.next() != XmlPullParser.END_TAG) {
String name = parser.getName(); if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// read NODE_META and NODE_DATA
if (name.equalsIgnoreCase(NODE_META)) {
readMeta(parser);
} else if (name.equalsIgnoreCase(NODE_DATA)) {
shares = readData(parser);
} else {
skip(parser);
}
if (name.equalsIgnoreCase(NODE_STATUS)) { }
setStatus(readNode(parser, NODE_STATUS)); return shares;
}
} else if (name.equalsIgnoreCase(NODE_STATUS_CODE)) { /**
setStatusCode(Integer.parseInt(readNode(parser, NODE_STATUS_CODE))); * Parse Meta node
*
* @param parser
* @throws XmlPullParserException
* @throws IOException
*/
private void readMeta(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, NODE_META);
//Log_OC.d(TAG, "---- NODE META ---");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
} else if (name.equalsIgnoreCase(NODE_MESSAGE)) { if (name.equalsIgnoreCase(NODE_STATUS)) {
setMessage(readNode(parser, NODE_MESSAGE)); setStatus(readNode(parser, NODE_STATUS));
} else { } else if (name.equalsIgnoreCase(NODE_STATUS_CODE)) {
skip(parser); setStatusCode(Integer.parseInt(readNode(parser, NODE_STATUS_CODE)));
}
} } else if (name.equalsIgnoreCase(NODE_MESSAGE)) {
} setMessage(readNode(parser, NODE_MESSAGE));
/** } else {
* Parse Data node skip(parser);
* @param parser }
* @return
* @throws XmlPullParserException
* @throws IOException
*/
private ArrayList<OCShare> readData(XmlPullParser parser) throws XmlPullParserException,
IOException {
ArrayList<OCShare> shares = new ArrayList<OCShare>();
OCShare share = null;
parser.require(XmlPullParser.START_TAG, ns, NODE_DATA); }
//Log_OC.d(TAG, "---- NODE DATA ---"); }
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equalsIgnoreCase(NODE_ELEMENT)) {
readElement(parser, shares);
} else if (name.equalsIgnoreCase(NODE_ID)) {// Parse Create XML Response
share = new OCShare();
String value = readNode(parser, NODE_ID);
share.setIdRemoteShared(Integer.parseInt(value));
} else if (name.equalsIgnoreCase(NODE_URL)) { /**
// NOTE: this field is received in all the public shares from OC 9.0.0 * Parse Data node
// in previous versions, it's received in the result of POST requests, but not *
// in GET requests * @param parser
share.setShareType(ShareType.PUBLIC_LINK); * @return
String value = readNode(parser, NODE_URL); * @throws XmlPullParserException
share.setShareLink(value); * @throws IOException
*/
private ArrayList<OCShare> readData(XmlPullParser parser) throws XmlPullParserException,
IOException {
ArrayList<OCShare> shares = new ArrayList<OCShare>();
OCShare share = null;
} else if (name.equalsIgnoreCase(NODE_TOKEN)) { parser.require(XmlPullParser.START_TAG, ns, NODE_DATA);
share.setToken(readNode(parser, NODE_TOKEN)); //Log_OC.d(TAG, "---- NODE DATA ---");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equalsIgnoreCase(NODE_ELEMENT)) {
readElement(parser, shares);
} else { } else if (name.equalsIgnoreCase(NODE_ID)) {// Parse Create XML Response
skip(parser); share = new OCShare();
String value = readNode(parser, NODE_ID);
} share.setIdRemoteShared(Integer.parseInt(value));
}
if (share != null) {
// this is the response of a request for creation; don't pass to isValidShare()
shares.add(share);
}
return shares; } else if (name.equalsIgnoreCase(NODE_URL)) {
// NOTE: this field is received in all the public shares from OC 9.0.0
// in previous versions, it's received in the result of POST requests, but not
// in GET requests
share.setShareType(ShareType.PUBLIC_LINK);
String value = readNode(parser, NODE_URL);
share.setShareLink(value);
} } else if (name.equalsIgnoreCase(NODE_TOKEN)) {
share.setToken(readNode(parser, NODE_TOKEN));
} else {
skip(parser);
/** }
* Parse Element node }
* @param parser
* @return
* @throws XmlPullParserException
* @throws IOException
*/
private void readElement(XmlPullParser parser, ArrayList<OCShare> shares)
throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, NODE_ELEMENT);
OCShare share = new OCShare();
//Log_OC.d(TAG, "---- NODE ELEMENT ---");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equalsIgnoreCase(NODE_ELEMENT)) { if (share != null) {
// patch to work around servers responding with extra <element> surrounding all // this is the response of a request for creation; don't pass to isValidShare()
// the shares on the same file before shares.add(share);
// https://github.com/owncloud/core/issues/6992 was fixed }
readElement(parser, shares);
} else if (name.equalsIgnoreCase(NODE_ID)) { return shares;
share.setIdRemoteShared(Integer.parseInt(readNode(parser, NODE_ID)));
} else if (name.equalsIgnoreCase(NODE_ITEM_TYPE)) { }
share.setIsFolder(readNode(parser, NODE_ITEM_TYPE).equalsIgnoreCase(TYPE_FOLDER));
fixPathForFolder(share);
} else if (name.equalsIgnoreCase(NODE_ITEM_SOURCE)) { /**
share.setItemSource(Long.parseLong(readNode(parser, NODE_ITEM_SOURCE))); * Parse Element node
*
* @param parser
* @return
* @throws XmlPullParserException
* @throws IOException
*/
private void readElement(XmlPullParser parser, ArrayList<OCShare> shares)
throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, NODE_ELEMENT);
} else if (name.equalsIgnoreCase(NODE_PARENT)) { OCShare share = new OCShare();
readNode(parser, NODE_PARENT);
} else if (name.equalsIgnoreCase(NODE_SHARE_TYPE)) { //Log_OC.d(TAG, "---- NODE ELEMENT ---");
int value = Integer.parseInt(readNode(parser, NODE_SHARE_TYPE)); while (parser.next() != XmlPullParser.END_TAG) {
share.setShareType(ShareType.fromValue(value)); if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
} else if (name.equalsIgnoreCase(NODE_SHARE_WITH)) { String name = parser.getName();
share.setShareWith(readNode(parser, NODE_SHARE_WITH));
} else if (name.equalsIgnoreCase(NODE_FILE_SOURCE)) { if (name.equalsIgnoreCase(NODE_ELEMENT)) {
share.setFileSource(Long.parseLong(readNode(parser, NODE_FILE_SOURCE))); // patch to work around servers responding with extra <element> surrounding all
// the shares on the same file before
// https://github.com/owncloud/core/issues/6992 was fixed
readElement(parser, shares);
} else if (name.equalsIgnoreCase(NODE_PATH)) { } else if (name.equalsIgnoreCase(NODE_ID)) {
share.setPath(readNode(parser, NODE_PATH)); share.setIdRemoteShared(Integer.parseInt(readNode(parser, NODE_ID)));
fixPathForFolder(share);
} else if (name.equalsIgnoreCase(NODE_PERMISSIONS)) { } else if (name.equalsIgnoreCase(NODE_ITEM_TYPE)) {
share.setPermissions(Integer.parseInt(readNode(parser, NODE_PERMISSIONS))); share.setIsFolder(readNode(parser, NODE_ITEM_TYPE).equalsIgnoreCase(TYPE_FOLDER));
fixPathForFolder(share);
} else if (name.equalsIgnoreCase(NODE_STIME)) { } else if (name.equalsIgnoreCase(NODE_ITEM_SOURCE)) {
share.setSharedDate(Long.parseLong(readNode(parser, NODE_STIME))); share.setItemSource(Long.parseLong(readNode(parser, NODE_ITEM_SOURCE)));
} else if (name.equalsIgnoreCase(NODE_EXPIRATION)) { } else if (name.equalsIgnoreCase(NODE_PARENT)) {
String value = readNode(parser, NODE_EXPIRATION); readNode(parser, NODE_PARENT);
if (!(value.length() == 0)) {
share.setExpirationDate(WebdavUtils.parseResponseDate(value).getTime());
}
} else if (name.equalsIgnoreCase(NODE_TOKEN)) { } else if (name.equalsIgnoreCase(NODE_SHARE_TYPE)) {
share.setToken(readNode(parser, NODE_TOKEN)); int value = Integer.parseInt(readNode(parser, NODE_SHARE_TYPE));
share.setShareType(ShareType.fromValue(value));
} else if (name.equalsIgnoreCase(NODE_STORAGE)) { } else if (name.equalsIgnoreCase(NODE_SHARE_WITH)) {
readNode(parser, NODE_STORAGE); share.setShareWith(readNode(parser, NODE_SHARE_WITH));
} else if (name.equalsIgnoreCase(NODE_MAIL_SEND)) {
readNode(parser, NODE_MAIL_SEND);
} else if (name.equalsIgnoreCase(NODE_SHARE_WITH_DISPLAY_NAME)) { } else if (name.equalsIgnoreCase(NODE_FILE_SOURCE)) {
share.setSharedWithDisplayName(readNode(parser, NODE_SHARE_WITH_DISPLAY_NAME)); share.setFileSource(Long.parseLong(readNode(parser, NODE_FILE_SOURCE)));
} else if (name.equalsIgnoreCase(NODE_URL)) { } else if (name.equalsIgnoreCase(NODE_PATH)) {
String value = readNode(parser, NODE_URL); share.setPath(readNode(parser, NODE_PATH));
share.setShareLink(value); fixPathForFolder(share);
} else if (name.equalsIgnoreCase(NODE_PERMISSIONS)) {
share.setPermissions(Integer.parseInt(readNode(parser, NODE_PERMISSIONS)));
} else if (name.equalsIgnoreCase(NODE_STIME)) {
share.setSharedDate(Long.parseLong(readNode(parser, NODE_STIME)));
} else if (name.equalsIgnoreCase(NODE_EXPIRATION)) {
String value = readNode(parser, NODE_EXPIRATION);
if (!(value.length() == 0)) {
share.setExpirationDate(WebdavUtils.parseResponseDate(value).getTime());
}
} else if (name.equalsIgnoreCase(NODE_TOKEN)) {
share.setToken(readNode(parser, NODE_TOKEN));
} else if (name.equalsIgnoreCase(NODE_STORAGE)) {
readNode(parser, NODE_STORAGE);
} else if (name.equalsIgnoreCase(NODE_MAIL_SEND)) {
readNode(parser, NODE_MAIL_SEND);
} else if (name.equalsIgnoreCase(NODE_SHARE_WITH_DISPLAY_NAME)) {
share.setSharedWithDisplayName(readNode(parser, NODE_SHARE_WITH_DISPLAY_NAME));
} else if (name.equalsIgnoreCase(NODE_URL)) {
String value = readNode(parser, NODE_URL);
share.setShareLink(value);
} else if (name.equalsIgnoreCase(NODE_NAME)) { } else if (name.equalsIgnoreCase(NODE_NAME)) {
share.setName(readNode(parser, NODE_NAME)); share.setName(readNode(parser, NODE_NAME));
} else { } else {
skip(parser); skip(parser);
} }
} }
if (isValidShare(share)) { if (isValidShare(share)) {
shares.add(share); shares.add(share);
} }
} }
private boolean isValidShare(OCShare share) { private boolean isValidShare(OCShare share) {
return (share.getRemoteId() > -1); return (share.getRemoteId() > -1);
} }
private void fixPathForFolder(OCShare share) { private void fixPathForFolder(OCShare share) {
if (share.isFolder() && share.getPath() != null && share.getPath().length() > 0 && if (share.isFolder() && share.getPath() != null && share.getPath().length() > 0 &&
!share.getPath().endsWith(FileUtils.PATH_SEPARATOR)) { !share.getPath().endsWith(FileUtils.PATH_SEPARATOR)) {
share.setPath(share.getPath() + FileUtils.PATH_SEPARATOR); share.setPath(share.getPath() + FileUtils.PATH_SEPARATOR);
} }
} }
/** /**
* Parse a node, to obtain its text. Needs readText method * Parse a node, to obtain its text. Needs readText method
* @param parser *
* @param node * @param parser
* @return Text of the node * @param node
* @throws XmlPullParserException * @return Text of the node
* @throws IOException * @throws XmlPullParserException
*/ * @throws IOException
private String readNode (XmlPullParser parser, String node) throws XmlPullParserException, */
IOException{ private String readNode(XmlPullParser parser, String node) throws XmlPullParserException,
parser.require(XmlPullParser.START_TAG, ns, node); IOException {
String value = readText(parser); parser.require(XmlPullParser.START_TAG, ns, node);
//Log_OC.d(TAG, "node= " + node + ", value= " + value); String value = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, node); //Log_OC.d(TAG, "node= " + node + ", value= " + value);
return value; parser.require(XmlPullParser.END_TAG, ns, node);
} return value;
}
/**
* Read the text from a node
* @param parser
* @return Text of the node
* @throws IOException
* @throws XmlPullParserException
*/
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
/** /**
* Skip tags in parser procedure * Read the text from a node
* @param parser *
* @throws XmlPullParserException * @param parser
* @throws IOException * @return Text of the node
*/ * @throws IOException
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { * @throws XmlPullParserException
if (parser.getEventType() != XmlPullParser.START_TAG) { */
throw new IllegalStateException(); private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
} String result = "";
int depth = 1; if (parser.next() == XmlPullParser.TEXT) {
while (depth != 0) { result = parser.getText();
switch (parser.next()) { parser.nextTag();
case XmlPullParser.END_TAG: }
depth--; return result;
break; }
case XmlPullParser.START_TAG:
depth++; /**
break; * Skip tags in parser procedure
} *
} * @param parser
} * @throws XmlPullParserException
* @throws IOException
*/
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
} }

View File

@ -33,6 +33,7 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.PutMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.FormBody;
import java.net.URL; import java.net.URL;
import java.text.DateFormat; import java.text.DateFormat;
@ -40,11 +41,9 @@ import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import okhttp3.FormBody;
/** /**
* Updates parameters of an existing Share resource, known its remote ID. * Updates parameters of an existing Share resource, known its remote ID.
* * <p>
* Allow updating several parameters, triggering a request to the server per parameter. * Allow updating several parameters, triggering a request to the server per parameter.
* *
* @author David A. Velasco * @author David A. Velasco
@ -64,7 +63,6 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
private static final String ENTITY_CONTENT_TYPE = "application/x-www-form-urlencoded"; private static final String ENTITY_CONTENT_TYPE = "application/x-www-form-urlencoded";
private static final String ENTITY_CHARSET = "UTF-8"; private static final String ENTITY_CHARSET = "UTF-8";
/** /**
* Identifier of the share to update * Identifier of the share to update
*/ */
@ -91,7 +89,6 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
private Boolean mPublicUpload; private Boolean mPublicUpload;
private String mName; private String mName;
/** /**
* Constructor. No update is initialized by default, need to be applied with setters below. * Constructor. No update is initialized by default, need to be applied with setters below.
* *
@ -105,13 +102,12 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
mPermissions = OCShare.DEFAULT_PERMISSION; mPermissions = OCShare.DEFAULT_PERMISSION;
} }
/** /**
* Set name to update in Share resource. Ignored by servers previous to version 10.0.0 * Set name to update in Share resource. Ignored by servers previous to version 10.0.0
* *
* @param name Name to set to the target share. * @param name Name to set to the target share.
* Empty string clears the current name. * Empty string clears the current name.
* Null results in no update applied to the name. * Null results in no update applied to the name.
*/ */
public void setName(String name) { public void setName(String name) {
this.mName = name; this.mName = name;
@ -128,7 +124,6 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
mPassword = password; mPassword = password;
} }
/** /**
* Set expiration date to update in Share resource. * Set expiration date to update in Share resource.
* *
@ -141,7 +136,6 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
mExpirationDateInMillis = expirationDateInMillis; mExpirationDateInMillis = expirationDateInMillis;
} }
/** /**
* Set permissions to update in Share resource. * Set permissions to update in Share resource.
* *
@ -155,8 +149,8 @@ public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResul
/** /**
* Enable upload permissions to update in Share resource. * Enable upload permissions to update in Share resource.
* *
* @param publicUpload Upload permission to set to the target share. * @param publicUpload Upload permission to set to the target share.
* Null results in no update applied to the upload permission. * Null results in no update applied to the upload permission.
*/ */
public void setPublicUpload(Boolean publicUpload) { public void setPublicUpload(Boolean publicUpload) {
mPublicUpload = publicUpload; mPublicUpload = publicUpload;

View File

@ -27,29 +27,22 @@ package com.owncloud.android.lib.resources.status;
/** /**
* Enum for Boolean Type in OCCapability parameters, with values: * Enum for Boolean Type in OCCapability parameters, with values:
* -1 - Unknown * -1 - Unknown
* 0 - False * 0 - False
* 1 - True * 1 - True
*/ */
public enum CapabilityBooleanType { public enum CapabilityBooleanType {
UNKNOWN (-1), UNKNOWN(-1),
FALSE (0), FALSE(0),
TRUE (1); TRUE(1);
private int value; private int value;
CapabilityBooleanType(int value) CapabilityBooleanType(int value) {
{
this.value = value; this.value = value;
} }
public int getValue() { public static CapabilityBooleanType fromValue(int value) {
return value; switch (value) {
}
public static CapabilityBooleanType fromValue(int value)
{
switch (value)
{
case -1: case -1:
return UNKNOWN; return UNKNOWN;
case 0: case 0:
@ -60,23 +53,27 @@ public enum CapabilityBooleanType {
return null; return null;
} }
public static CapabilityBooleanType fromBooleanValue(boolean boolValue){ public static CapabilityBooleanType fromBooleanValue(boolean boolValue) {
if (boolValue){ if (boolValue) {
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
} }
} }
public boolean isUnknown(){ public int getValue() {
return value;
}
public boolean isUnknown() {
return getValue() == -1; return getValue() == -1;
} }
public boolean isFalse(){ public boolean isFalse() {
return getValue() == 0; return getValue() == 0;
} }
public boolean isTrue(){ public boolean isTrue() {
return getValue() == 1; return getValue() == 1;
} }

View File

@ -24,7 +24,6 @@
* *
*/ */
package com.owncloud.android.lib.resources.status; package com.owncloud.android.lib.resources.status;
import android.net.Uri; import android.net.Uri;
@ -35,7 +34,6 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.json.JSONObject; import org.json.JSONObject;
import java.net.URL; import java.net.URL;
@ -109,10 +107,8 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability
private static final String PROPERTY_UNDELETE = "undelete"; private static final String PROPERTY_UNDELETE = "undelete";
private static final String PROPERTY_VERSIONING = "versioning"; private static final String PROPERTY_VERSIONING = "versioning";
/** /**
* Constructor * Constructor
*
*/ */
public GetRemoteCapabilitiesOperation() { public GetRemoteCapabilitiesOperation() {
@ -135,7 +131,7 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability
int status = client.executeHttpMethod(getMethod); int status = client.executeHttpMethod(getMethod);
String response = getMethod.getResponseBodyAsString(); String response = getMethod.getResponseBodyAsString();
if(isSuccess(status)) { if (isSuccess(status)) {
Log_OC.d(TAG, "Successful response: " + response); Log_OC.d(TAG, "Successful response: " + response);
// Parse the response // Parse the response
@ -185,12 +181,12 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability
JSONObject respPublic = respFilesSharing.getJSONObject(NODE_PUBLIC); JSONObject respPublic = respFilesSharing.getJSONObject(NODE_PUBLIC);
capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromBooleanValue( capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromBooleanValue(
respPublic.getBoolean(PROPERTY_ENABLED))); respPublic.getBoolean(PROPERTY_ENABLED)));
if(respPublic.has(NODE_PASSWORD)) { if (respPublic.has(NODE_PASSWORD)) {
capability.setFilesSharingPublicPasswordEnforced( capability.setFilesSharingPublicPasswordEnforced(
CapabilityBooleanType.fromBooleanValue( CapabilityBooleanType.fromBooleanValue(
respPublic.getJSONObject(NODE_PASSWORD).getBoolean(PROPERTY_ENFORCED))); respPublic.getJSONObject(NODE_PASSWORD).getBoolean(PROPERTY_ENFORCED)));
} }
if(respPublic.has(NODE_EXPIRE_DATE)){ if (respPublic.has(NODE_EXPIRE_DATE)) {
JSONObject respExpireDate = respPublic.getJSONObject(NODE_EXPIRE_DATE); JSONObject respExpireDate = respPublic.getJSONObject(NODE_EXPIRE_DATE);
capability.setFilesSharingPublicExpireDateEnabled( capability.setFilesSharingPublicExpireDateEnabled(
CapabilityBooleanType.fromBooleanValue( CapabilityBooleanType.fromBooleanValue(
@ -205,7 +201,7 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability
respExpireDate.getBoolean(PROPERTY_ENFORCED))); respExpireDate.getBoolean(PROPERTY_ENFORCED)));
} }
} }
if (respPublic.has(PROPERTY_UPLOAD)){ if (respPublic.has(PROPERTY_UPLOAD)) {
capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromBooleanValue( capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromBooleanValue(
respPublic.getBoolean(PROPERTY_UPLOAD))); respPublic.getBoolean(PROPERTY_UPLOAD)));
} }
@ -230,14 +226,13 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability
if (respFilesSharing.has(NODE_FEDERATION)) { if (respFilesSharing.has(NODE_FEDERATION)) {
JSONObject respFederation = respFilesSharing.getJSONObject(NODE_FEDERATION); JSONObject respFederation = respFilesSharing.getJSONObject(NODE_FEDERATION);
capability.setFilesSharingFederationOutgoing( capability.setFilesSharingFederationOutgoing(
CapabilityBooleanType.fromBooleanValue(respFederation.getBoolean(PROPERTY_OUTGOING))); CapabilityBooleanType.fromBooleanValue(respFederation.getBoolean(PROPERTY_OUTGOING)));
capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromBooleanValue( capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromBooleanValue(
respFederation.getBoolean(PROPERTY_INCOMING))); respFederation.getBoolean(PROPERTY_INCOMING)));
} }
Log_OC.d(TAG, "*** Added " + NODE_FILES_SHARING); Log_OC.d(TAG, "*** Added " + NODE_FILES_SHARING);
} }
if (respCapabilities.has(NODE_FILES)) { if (respCapabilities.has(NODE_FILES)) {
JSONObject respFiles = respCapabilities.getJSONObject(NODE_FILES); JSONObject respFiles = respCapabilities.getJSONObject(NODE_FILES);
// Add files // Add files

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -34,13 +34,12 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import javax.net.ssl.SSLException;
import java.net.URL; import java.net.URL;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLException;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
@ -98,11 +97,11 @@ public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
String redirectedLocation = mLatestResult.getRedirectedLocation(); String redirectedLocation = mLatestResult.getRedirectedLocation();
while (redirectedLocation != null && redirectedLocation.length() > 0 while (redirectedLocation != null && redirectedLocation.length() > 0
&& !mLatestResult.isSuccess()) { && !mLatestResult.isSuccess()) {
isRedirectToNonSecureConnection |= ( isRedirectToNonSecureConnection |= (
baseUrlSt.startsWith(HTTPS_PREFIX) && baseUrlSt.startsWith(HTTPS_PREFIX) &&
redirectedLocation.startsWith(HTTP_PREFIX) redirectedLocation.startsWith(HTTP_PREFIX)
); );
getMethod = new GetMethod(new URL(redirectedLocation)); getMethod = new GetMethod(new URL(redirectedLocation));
@ -128,13 +127,13 @@ public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
if (isRedirectToNonSecureConnection) { if (isRedirectToNonSecureConnection) {
mLatestResult = new RemoteOperationResult<>( mLatestResult = new RemoteOperationResult<>(
RemoteOperationResult.ResultCode. RemoteOperationResult.ResultCode.
OK_REDIRECT_TO_NON_SECURE_CONNECTION); OK_REDIRECT_TO_NON_SECURE_CONNECTION);
} else { } else {
mLatestResult = new RemoteOperationResult<>( mLatestResult = new RemoteOperationResult<>(
baseUrlSt.startsWith(HTTPS_PREFIX) ? baseUrlSt.startsWith(HTTPS_PREFIX) ?
RemoteOperationResult.ResultCode.OK_SSL : RemoteOperationResult.ResultCode.OK_SSL :
RemoteOperationResult.ResultCode.OK_NO_SSL); RemoteOperationResult.ResultCode.OK_NO_SSL);
} }
mLatestResult.setData(ocVersion); mLatestResult.setData(ocVersion);
@ -147,7 +146,7 @@ public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
} catch (JSONException e) { } catch (JSONException e) {
mLatestResult = new RemoteOperationResult<>( mLatestResult = new RemoteOperationResult<>(
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED); RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
} catch (Exception e) { } catch (Exception e) {
mLatestResult = new RemoteOperationResult<>(e); mLatestResult = new RemoteOperationResult<>(e);
@ -158,7 +157,7 @@ public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
} else if (mLatestResult.getException() != null) { } else if (mLatestResult.getException() != null) {
Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(), Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(),
mLatestResult.getException()); mLatestResult.getException());
} else { } else {
Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); Log_OC.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage());
@ -169,9 +168,9 @@ public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
private boolean isOnline() { private boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) mContext ConnectivityManager cm = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE); .getSystemService(Context.CONNECTIVITY_SERVICE);
return cm != null && cm.getActiveNetworkInfo() != null return cm != null && cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isConnectedOrConnecting(); && cm.getActiveNetworkInfo().isConnectedOrConnecting();
} }
@Override @Override

View File

@ -101,7 +101,6 @@ public class OCCapability {
mFilesVersioning = CapabilityBooleanType.UNKNOWN; mFilesVersioning = CapabilityBooleanType.UNKNOWN;
} }
// Getters and Setters // Getters and Setters
public String getAccountName() { public String getAccountName() {
return mAccountName; return mAccountName;
@ -159,7 +158,6 @@ public class OCCapability {
this.mVersionEdition = versionEdition; this.mVersionEdition = versionEdition;
} }
public int getCorePollinterval() { public int getCorePollinterval() {
return mCorePollinterval; return mCorePollinterval;
} }
@ -216,7 +214,6 @@ public class OCCapability {
this.mFilesSharingPublicExpireDateEnforced = filesSharingPublicExpireDateEnforced; this.mFilesSharingPublicExpireDateEnforced = filesSharingPublicExpireDateEnforced;
} }
public CapabilityBooleanType getFilesSharingPublicSendMail() { public CapabilityBooleanType getFilesSharingPublicSendMail() {
return mFilesSharingPublicSendMail; return mFilesSharingPublicSendMail;
} }

View File

@ -1,23 +1,23 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -106,7 +106,7 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
@Override @Override
public int compareTo(OwnCloudVersion another) { public int compareTo(OwnCloudVersion another) {
return another.mVersion == mVersion ? 0 return another.mVersion == mVersion ? 0
: another.mVersion < mVersion ? 1 : -1; : another.mVersion < mVersion ? 1 : -1;
} }
private void parseVersion(String version) { private void parseVersion(String version) {
@ -139,7 +139,6 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
return versionValue; return versionValue;
} }
public boolean isChunkedUploadSupported() { public boolean isChunkedUploadSupported() {
return (mVersion >= MINIMUN_VERSION_FOR_CHUNKED_UPLOADS); return (mVersion >= MINIMUN_VERSION_FOR_CHUNKED_UPLOADS);
} }
@ -185,8 +184,8 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
*/ */
public boolean isPreemptiveAuthenticationPreferred() { public boolean isPreemptiveAuthenticationPreferred() {
return ( return (
(mVersion < MINIMUM_VERSION_WITH_SESSION_MONITORING) || (mVersion < MINIMUM_VERSION_WITH_SESSION_MONITORING) ||
(mVersion >= MINIMUM_VERSION_WITH_SESSION_MONITORING_WORKING_IN_PREEMPTIVE_MODE) (mVersion >= MINIMUM_VERSION_WITH_SESSION_MONITORING_WORKING_IN_PREEMPTIVE_MODE)
); );
} }

View File

@ -43,6 +43,7 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
/** /**
* Gets avatar about the user logged in, if available * Gets avatar about the user logged in, if available
*
* @author David A. Velasco * @author David A. Velasco
* @author David González Verdugo * @author David González Verdugo
*/ */
@ -52,7 +53,9 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation<GetRemoteUserA
private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/"; private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/";
/** Desired size in pixels of the squared image */ /**
* Desired size in pixels of the squared image
*/
private int mDimension; private int mDimension;
/** /**
@ -77,7 +80,7 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation<GetRemoteUserA
try { try {
final String url = final String url =
client.getBaseUri() + NON_OFFICIAL_AVATAR_PATH + client.getBaseUri() + NON_OFFICIAL_AVATAR_PATH +
client.getCredentials().getUsername() + "/" + mDimension; client.getCredentials().getUsername() + "/" + mDimension;
Log_OC.d(TAG, "avatar URI: " + url); Log_OC.d(TAG, "avatar URI: " + url);
getMethod = new GetMethod(new URL(url)); getMethod = new GetMethod(new URL(url));
@ -99,7 +102,7 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation<GetRemoteUserA
if (contentType == null || !contentType.startsWith("image")) { if (contentType == null || !contentType.startsWith("image")) {
Log_OC.e( Log_OC.e(
TAG, "Not an image, failing with no avatar" TAG, "Not an image, failing with no avatar"
); );
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.FILE_NOT_FOUND); result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.FILE_NOT_FOUND);
return result; return result;

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -30,7 +30,6 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.json.JSONObject; import org.json.JSONObject;
import java.net.URL; import java.net.URL;

View File

@ -27,6 +27,9 @@
package com.owncloud.android.lib.resources.users; package com.owncloud.android.lib.resources.users;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.property.QuotaAvailableBytes;
import at.bitfire.dav4android.property.QuotaUsedBytes;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils; import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
@ -39,10 +42,6 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.property.QuotaAvailableBytes;
import at.bitfire.dav4android.property.QuotaUsedBytes;
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0; import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
@ -52,26 +51,7 @@ import static com.owncloud.android.lib.common.operations.RemoteOperationResult.R
*/ */
public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQuotaOperation.RemoteQuota> { public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQuotaOperation.RemoteQuota> {
static public class RemoteQuota {
long mFree, mUsed, mTotal;
double mRelative;
public RemoteQuota(long free, long used, long total, double relative) {
mFree = free;
mUsed = used;
mTotal = total;
mRelative = relative;
}
public long getFree() { return mFree; }
public long getUsed() { return mUsed; }
public long getTotal() { return mTotal; }
public double getRelative() { return mRelative; }
}
private static final String TAG = GetRemoteUserQuotaOperation.class.getSimpleName(); private static final String TAG = GetRemoteUserQuotaOperation.class.getSimpleName();
private String mRemotePath; private String mRemotePath;
/** /**
@ -112,7 +92,6 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQu
} catch (Exception e) { } catch (Exception e) {
result = new RemoteOperationResult<>(e); result = new RemoteOperationResult<>(e);
} finally { } finally {
if (result.isSuccess()) { if (result.isSuccess()) {
Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage()); Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage());
@ -143,11 +122,13 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQu
long quotaAvailable = 0; long quotaAvailable = 0;
long quotaUsed = 0; long quotaUsed = 0;
for(Property property : properties) { for (Property property : properties) {
if(property instanceof QuotaAvailableBytes) if (property instanceof QuotaAvailableBytes) {
quotaAvailable = ((QuotaAvailableBytes) property).getQuotaAvailableBytes(); quotaAvailable = ((QuotaAvailableBytes) property).getQuotaAvailableBytes();
if(property instanceof QuotaUsedBytes) }
if (property instanceof QuotaUsedBytes) {
quotaUsed = ((QuotaUsedBytes) property).getQuotaUsedBytes(); quotaUsed = ((QuotaUsedBytes) property).getQuotaUsedBytes();
}
} }
// If there's a special case, quota available will contain a negative code // If there's a special case, quota available will contain a negative code
@ -163,8 +144,8 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQu
); );
} else { } else {
long totalQuota = quotaAvailable + quotaUsed; long totalQuota = quotaAvailable + quotaUsed;
double relativeQuota = (double)(quotaUsed * 100)/totalQuota; double relativeQuota = (double) (quotaUsed * 100) / totalQuota;
double roundedRelativeQuota = Math.round(relativeQuota * 100)/100.0d; double roundedRelativeQuota = Math.round(relativeQuota * 100) / 100.0d;
return new RemoteQuota( return new RemoteQuota(
quotaAvailable, quotaAvailable,
@ -174,4 +155,33 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQu
); );
} }
} }
static public class RemoteQuota {
long mFree, mUsed, mTotal;
double mRelative;
public RemoteQuota(long free, long used, long total, double relative) {
mFree = free;
mUsed = used;
mTotal = total;
mRelative = relative;
}
public long getFree() {
return mFree;
}
public long getUsed() {
return mUsed;
}
public long getTotal() {
return mTotal;
}
public double getRelative() {
return mRelative;
}
}
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.owncloud.android</groupId> <groupId>com.owncloud.android</groupId>
@ -19,7 +19,7 @@
</properties> </properties>
<description>owncloud-android-library for Owncloud for Android</description> <description>owncloud-android-library for Owncloud for Android</description>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@ -19,7 +19,7 @@ android {
packagingOptions { packagingOptions {
exclude 'META-INF/LICENSE.txt' exclude 'META-INF/LICENSE.txt'
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8

View File

@ -23,12 +23,12 @@
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest package="com.owncloud.android.lib.sampleclient"
package="com.owncloud.android.lib.sampleclient" xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name"> android:label="@string/app_name">
@ -39,8 +39,8 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
> >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -32,15 +32,15 @@ import android.widget.TextView;
import com.owncloud.android.lib.resources.files.RemoteFile; import com.owncloud.android.lib.resources.files.RemoteFile;
public class FilesArrayAdapter extends ArrayAdapter<RemoteFile> { public class FilesArrayAdapter extends ArrayAdapter<RemoteFile> {
public FilesArrayAdapter(Context context, int resource) { public FilesArrayAdapter(Context context, int resource) {
super(context, resource); super(context, resource);
} }
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView)super.getView(position, convertView, parent); TextView textView = (TextView) super.getView(position, convertView, parent);
textView.setText(getItem(position).getRemotePath()); textView.setText(getItem(position).getRemotePath());
return textView; return textView;
} }
} }

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2018 ownCloud GmbH. * Copyright (C) 2018 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
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -66,245 +66,245 @@ import java.util.List;
import static android.content.ContentValues.TAG; import static android.content.ContentValues.TAG;
public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener { public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener {
private static String LOG_TAG = MainActivity.class.getCanonicalName(); private static String LOG_TAG = MainActivity.class.getCanonicalName();
private Handler mHandler; private Handler mHandler;
private OwnCloudClient mClient; private OwnCloudClient mClient;
private FilesArrayAdapter mFilesAdapter; private FilesArrayAdapter mFilesAdapter;
private View mFrame; private View mFrame;
/** Called when the activity is first created. */ /**
* Called when the activity is first created.
*/
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.main); setContentView(R.layout.main);
mHandler = new Handler(); mHandler = new Handler();
final Uri serverUri = Uri.parse(getString(R.string.server_base_url));
OwnCloudClientManagerFactory.setUserAgent(getUserAgent()); final Uri serverUri = Uri.parse(getString(R.string.server_base_url));
mClient = OwnCloudClientFactory.createOwnCloudClient(serverUri, this, true);
mClient.setCredentials( OwnCloudClientManagerFactory.setUserAgent(getUserAgent());
OwnCloudCredentialsFactory.newBasicCredentials( mClient = OwnCloudClientFactory.createOwnCloudClient(serverUri, this, true);
getString(R.string.username),
getString(R.string.password) mClient.setCredentials(
) OwnCloudCredentialsFactory.newBasicCredentials(
); getString(R.string.username),
getString(R.string.password)
mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list); )
((ListView)findViewById(R.id.list_view)).setAdapter(mFilesAdapter); );
// TODO move to background thread or task mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list);
AssetManager assets = getAssets(); ((ListView) findViewById(R.id.list_view)).setAdapter(mFilesAdapter);
try {
String sampleFileName = getString(R.string.sample_file_name); // TODO move to background thread or task
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); AssetManager assets = getAssets();
upFolder.mkdir(); try {
File upFile = new File(upFolder, sampleFileName); String sampleFileName = getString(R.string.sample_file_name);
FileOutputStream fos = new FileOutputStream(upFile); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
InputStream is = assets.open(sampleFileName); upFolder.mkdir();
int count = 0; File upFile = new File(upFolder, sampleFileName);
byte[] buffer = new byte[1024]; FileOutputStream fos = new FileOutputStream(upFile);
while ((count = is.read(buffer, 0, buffer.length)) >= 0) { InputStream is = assets.open(sampleFileName);
fos.write(buffer, 0, count); int count = 0;
} byte[] buffer = new byte[1024];
is.close(); while ((count = is.read(buffer, 0, buffer.length)) >= 0) {
fos.close(); fos.write(buffer, 0, count);
} catch (IOException e) { }
Toast.makeText(this, R.string.error_copying_sample_file, Toast.LENGTH_SHORT).show(); is.close();
Log.e(LOG_TAG, getString(R.string.error_copying_sample_file), e); fos.close();
} } catch (IOException e) {
Toast.makeText(this, R.string.error_copying_sample_file, Toast.LENGTH_SHORT).show();
mFrame = findViewById(R.id.frame); Log.e(LOG_TAG, getString(R.string.error_copying_sample_file), e);
}
mFrame = findViewById(R.id.frame);
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File upFile = upFolder.listFiles()[0]; File upFile = upFolder.listFiles()[0];
upFile.delete(); upFile.delete();
upFolder.delete(); upFolder.delete();
super.onDestroy(); super.onDestroy();
} }
public void onClickHandler(View button) { public void onClickHandler(View button) {
switch (button.getId()) { switch (button.getId()) {
case R.id.button_refresh: case R.id.button_refresh:
startRefresh(); startRefresh();
break; break;
case R.id.button_upload: case R.id.button_upload:
startUpload(); startUpload();
break; break;
case R.id.button_delete_remote: case R.id.button_delete_remote:
startRemoteDeletion(); startRemoteDeletion();
break; break;
case R.id.button_download: case R.id.button_download:
startDownload(); startDownload();
break; break;
case R.id.button_delete_local: case R.id.button_delete_local:
startLocalDeletion(); startLocalDeletion();
break; break;
default: default:
Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show();
} }
} }
private void startRefresh() { private void startRefresh() {
ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR); ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR);
refreshOperation.execute(mClient, this, mHandler); refreshOperation.execute(mClient, this, mHandler);
} }
private void startUpload() { private void startUpload() {
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
String mimeType = getString(R.string.sample_file_mimetype); String mimeType = getString(R.string.sample_file_mimetype);
// Get the last modification date of the file from the file system // Get the last modification date of the file from the file system
Long timeStampLong = fileToUpload.lastModified()/1000; Long timeStampLong = fileToUpload.lastModified() / 1000;
String timeStamp = timeStampLong.toString(); String timeStamp = timeStampLong.toString();
UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(),
remotePath, mimeType, timeStamp); remotePath, mimeType, timeStamp);
uploadOperation.addDatatransferProgressListener(this); uploadOperation.addDatatransferProgressListener(this);
uploadOperation.execute(mClient, this, mHandler); uploadOperation.execute(mClient, this, mHandler);
} }
private void startRemoteDeletion() { private void startRemoteDeletion() {
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath); RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
removeOperation.execute(mClient, this, mHandler); removeOperation.execute(mClient, this, mHandler);
} }
private void startDownload() { private void startDownload() {
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path)); File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
downFolder.mkdir(); downFolder.mkdir();
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
File fileToUpload = upFolder.listFiles()[0]; File fileToUpload = upFolder.listFiles()[0];
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath,
downFolder.getAbsolutePath()); downFolder.getAbsolutePath());
downloadOperation.addDatatransferProgressListener(this); downloadOperation.addDatatransferProgressListener(this);
downloadOperation.execute(mClient, this, mHandler); downloadOperation.execute(mClient, this, mHandler);
} }
private void startLocalDeletion() { private void startLocalDeletion() {
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path)); File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
File downloadedFile = downFolder.listFiles()[0]; File downloadedFile = downFolder.listFiles()[0];
if (!downloadedFile.delete() && downloadedFile.exists()) { if (!downloadedFile.delete() && downloadedFile.exists()) {
Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show();
} else { } else {
((TextView) findViewById(R.id.download_progress)).setText("0%"); ((TextView) findViewById(R.id.download_progress)).setText("0%");
findViewById(R.id.frame).setBackgroundDrawable(null); findViewById(R.id.frame).setBackgroundDrawable(null);
} }
} }
@Override @Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
if (!result.isSuccess()) { if (!result.isSuccess()) {
Toast.makeText(this, R.string.todo_operation_finished_in_fail, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.todo_operation_finished_in_fail, Toast.LENGTH_SHORT).show();
Log.e(LOG_TAG, result.getLogMessage(), result.getException()); Log.e(LOG_TAG, result.getLogMessage(), result.getException());
} else if (operation instanceof ReadRemoteFolderOperation) {
onSuccessfulRefresh((ReadRemoteFolderOperation)operation, result);
} else if (operation instanceof com.owncloud.android.lib.resources.files.UploadRemoteFileOperation) {
onSuccessfulUpload((com.owncloud.android.lib.resources.files.UploadRemoteFileOperation)operation, result);
} else if (operation instanceof RemoveRemoteFileOperation ) {
onSuccessfulRemoteDeletion((RemoveRemoteFileOperation)operation, result);
} else if (operation instanceof DownloadRemoteFileOperation ) { } else if (operation instanceof ReadRemoteFolderOperation) {
onSuccessfulDownload(); onSuccessfulRefresh((ReadRemoteFolderOperation) operation, result);
} else {
Toast.makeText(this, R.string.todo_operation_finished_in_success, Toast.LENGTH_SHORT).show();
}
}
private void onSuccessfulRefresh(ReadRemoteFolderOperation operation, RemoteOperationResult result) { } else if (operation instanceof com.owncloud.android.lib.resources.files.UploadRemoteFileOperation) {
mFilesAdapter.clear(); onSuccessfulUpload((com.owncloud.android.lib.resources.files.UploadRemoteFileOperation) operation, result);
List<RemoteFile> files = new ArrayList<>();
for(RemoteFile remoteFile: (List<RemoteFile>) result.getData()) { } else if (operation instanceof RemoveRemoteFileOperation) {
onSuccessfulRemoteDeletion((RemoveRemoteFileOperation) operation, result);
} else if (operation instanceof DownloadRemoteFileOperation) {
onSuccessfulDownload();
} else {
Toast.makeText(this, R.string.todo_operation_finished_in_success, Toast.LENGTH_SHORT).show();
}
}
private void onSuccessfulRefresh(ReadRemoteFolderOperation operation, RemoteOperationResult result) {
mFilesAdapter.clear();
List<RemoteFile> files = new ArrayList<>();
for (RemoteFile remoteFile : (List<RemoteFile>) result.getData()) {
files.add(remoteFile); files.add(remoteFile);
} }
if (files != null) { if (files != null) {
Iterator<RemoteFile> it = files.iterator(); Iterator<RemoteFile> it = files.iterator();
while (it.hasNext()) { while (it.hasNext()) {
mFilesAdapter.add(it.next()); mFilesAdapter.add(it.next());
} }
mFilesAdapter.remove(mFilesAdapter.getItem(0)); mFilesAdapter.remove(mFilesAdapter.getItem(0));
} }
mFilesAdapter.notifyDataSetChanged(); mFilesAdapter.notifyDataSetChanged();
} }
private void onSuccessfulUpload(com.owncloud.android.lib.resources.files.UploadRemoteFileOperation operation, RemoteOperationResult result) { private void onSuccessfulUpload(com.owncloud.android.lib.resources.files.UploadRemoteFileOperation operation, RemoteOperationResult result) {
startRefresh(); startRefresh();
} }
private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) { private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) {
startRefresh(); startRefresh();
TextView progressView = (TextView) findViewById(R.id.upload_progress); TextView progressView = (TextView) findViewById(R.id.upload_progress);
if (progressView != null) { if (progressView != null) {
progressView.setText("0%"); progressView.setText("0%");
} }
} }
private void onSuccessfulDownload() { private void onSuccessfulDownload() {
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path)); File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
File downloadedFile = downFolder.listFiles()[0]; File downloadedFile = downFolder.listFiles()[0];
BitmapDrawable bDraw = new BitmapDrawable(getResources(), downloadedFile.getAbsolutePath()); BitmapDrawable bDraw = new BitmapDrawable(getResources(), downloadedFile.getAbsolutePath());
mFrame.setBackgroundDrawable(bDraw); mFrame.setBackgroundDrawable(bDraw);
} }
@Override @Override
public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) { public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) {
final long percentage = (totalToTransfer > 0 ? totalTransferredSoFar * 100 / totalToTransfer : 0); final long percentage = (totalToTransfer > 0 ? totalTransferredSoFar * 100 / totalToTransfer : 0);
final boolean upload = fileName.contains(getString(R.string.upload_folder_path)); final boolean upload = fileName.contains(getString(R.string.upload_folder_path));
Log.d(LOG_TAG, "progressRate " + percentage); Log.d(LOG_TAG, "progressRate " + percentage);
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
TextView progressView = null; TextView progressView = null;
if (upload) { if (upload) {
progressView = findViewById(R.id.upload_progress); progressView = findViewById(R.id.upload_progress);
} else { } else {
progressView = findViewById(R.id.download_progress); progressView = findViewById(R.id.download_progress);
} }
if (progressView != null) { if (progressView != null) {
progressView.setText(Long.toString(percentage) + "%"); progressView.setText(Long.toString(percentage) + "%");
} }
} }
}); });
} }
// user agent // user agent
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
private String getUserAgent() { private String getUserAgent() {
String appString = getResources().getString(R.string.user_agent); String appString = getResources().getString(R.string.user_agent);
String packageName = getPackageName(); String packageName = getPackageName();
String version = ""; String version = "";
PackageInfo pInfo; PackageInfo pInfo;
try { try {
pInfo = getPackageManager().getPackageInfo(packageName, 0); pInfo = getPackageManager().getPackageInfo(packageName, 0);
if (pInfo != null) { if (pInfo != null) {
version = pInfo.versionName; version = pInfo.versionName;
} }
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
Log_OC.e(TAG, "Trying to get packageName", e.getCause()); Log_OC.e(TAG, "Trying to get packageName", e.getCause());
} }
// Mozilla/5.0 (Android) ownCloud-android/1.7.0 // Mozilla/5.0 (Android) ownCloud-android/1.7.0
return String.format(appString, version); return String.format(appString, version);
} }
} }

View File

@ -22,8 +22,8 @@
THE SOFTWARE. THE SOFTWARE.
--> -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
/> />

View File

@ -33,58 +33,58 @@
style="@style/ButtonStyle" style="@style/ButtonStyle"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:text="@string/refresh"
android:onClick="onClickHandler" android:onClick="onClickHandler"
android:text="@string/refresh"
/> />
<ListView <ListView
android:id="@+id/list_view" android:id="@+id/list_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/button_refresh"
android:layout_above="@+id/button_upload" android:layout_above="@+id/button_upload"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_below="@+id/button_refresh"
> >
</ListView> </ListView>
<Button <Button
android:id="@+id/button_upload" android:id="@+id/button_upload"
style="@style/ButtonStyle" style="@style/ButtonStyle"
android:layout_alignParentLeft="true"
android:layout_above="@+id/frame" android:layout_above="@+id/frame"
android:text="@string/upload" android:layout_alignParentLeft="true"
android:onClick="onClickHandler" android:onClick="onClickHandler"
android:text="@string/upload"
/> />
<TextView <TextView
android:id="@+id/upload_progress" android:id="@+id/upload_progress"
style="@style/ProgressStyle" style="@style/ProgressStyle"
android:layout_below="@id/list_view"
android:layout_above="@id/frame" android:layout_above="@id/frame"
android:layout_toRightOf="@id/button_upload" android:layout_below="@id/list_view"
android:layout_toLeftOf="@+id/button_delete_remote" android:layout_toLeftOf="@+id/button_delete_remote"
android:layout_toRightOf="@id/button_upload"
android:gravity="center" android:gravity="center"
android:textSize="14sp"
android:text="0%" android:text="0%"
android:textSize="14sp"
/> />
<Button <Button
android:id="@id/button_delete_remote" android:id="@id/button_delete_remote"
style="@style/ButtonStyle" style="@style/ButtonStyle"
android:layout_alignParentRight="true"
android:layout_above="@id/frame" android:layout_above="@id/frame"
android:text="@string/delete_remote_file" android:layout_alignParentRight="true"
android:onClick="onClickHandler" android:onClick="onClickHandler"
android:text="@string/delete_remote_file"
/> />
<FrameLayout <FrameLayout
android:id="@id/frame" android:id="@id/frame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/frame_height" android:layout_height="@dimen/frame_height"
android:layout_above="@+id/button_download"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_above="@+id/button_download"
> >
</FrameLayout> </FrameLayout>
@ -93,20 +93,20 @@
style="@style/ButtonStyle" style="@style/ButtonStyle"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:text="@string/download"
android:onClick="onClickHandler" android:onClick="onClickHandler"
android:text="@string/download"
/> />
<TextView <TextView
android:id="@+id/download_progress" android:id="@+id/download_progress"
style="@style/ProgressStyle" style="@style/ProgressStyle"
android:layout_below="@id/frame"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/button_download" android:layout_below="@id/frame"
android:layout_toLeftOf="@+id/button_delete_local" android:layout_toLeftOf="@+id/button_delete_local"
android:layout_toRightOf="@id/button_download"
android:gravity="center" android:gravity="center"
android:textSize="14sp"
android:text="0%" android:text="0%"
android:textSize="14sp"
/> />
<Button <Button
@ -114,8 +114,8 @@
style="@style/ButtonStyle" style="@style/ButtonStyle"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:text="@string/delete_local_file"
android:onClick="onClickHandler" android:onClick="onClickHandler"
android:text="@string/delete_local_file"
/> />
</RelativeLayout> </RelativeLayout>

View File

@ -22,13 +22,15 @@
THE SOFTWARE. THE SOFTWARE.
--> -->
<resources xmlns:android="http://schemas.android.com/apk/res/android"> <resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="ButtonStyle" parent="@android:style/Widget.Holo.Button"> <style name="ButtonStyle" parent="@android:style/Widget.Holo.Button">
<item name="android:layout_width">120dp</item> <item name="android:layout_width">120dp</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:textSize">12sp</item> <item name="android:textSize">12sp</item>
</style> </style>
<style name="ProgressStyle" parent="@android:style/Widget.Holo.TextView"> <style name="ProgressStyle" parent="@android:style/Widget.Holo.TextView">
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>

View File

@ -22,7 +22,7 @@
THE SOFTWARE. THE SOFTWARE.
--> -->
<resources> <resources>
<dimen name="frame_height">120dp</dimen> <dimen name="frame_height">120dp</dimen>
</resources> </resources>

View File

@ -26,5 +26,5 @@
<string name="server_base_url"></string> <string name="server_base_url"></string>
<string name="username"></string> <string name="username"></string>
<string name="password"></string> <string name="password"></string>
<string name ="user_agent">Mozilla/5.0 (Android) ownCloud sample </string> <string name="user_agent">Mozilla/5.0 (Android) ownCloud sample </string>
</resources> </resources>

Some files were not shown because too many files have changed in this diff Show More