diff --git a/src/com/owncloud/android/lib/common/OwnCloudClient.java b/src/com/owncloud/android/lib/common/OwnCloudClient.java index b6804708..7364f345 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClient.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClient.java @@ -49,13 +49,14 @@ import android.net.Uri; import com.owncloud.android.lib.common.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials; import com.owncloud.android.lib.common.accounts.AccountUtils; +import com.owncloud.android.lib.common.network.RedirectionPath; import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.utils.Log_OC; public class OwnCloudClient extends HttpClient { private static final String TAG = OwnCloudClient.class.getSimpleName(); - private static final int MAX_REDIRECTIONS_COUNT = 3; + public static final int MAX_REDIRECTIONS_COUNT = 3; private static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true; @@ -168,13 +169,13 @@ public class OwnCloudClient extends HttpClient { * * The timeouts are both in milliseconds; 0 means 'infinite'; * < 0 means 'do not change the default' - * + * * @param method HTTP method request. * @param readTimeout Timeout to set for data reception * @param connectionTimeout Timeout to set for connection establishment */ - public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) - throws HttpException, IOException { + public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws IOException { + int oldSoTimeout = getParams().getSoTimeout(); int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout(); try { @@ -191,55 +192,53 @@ public class OwnCloudClient extends HttpClient { getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout); } } - - - @Override - public int executeMethod(HttpMethod method) throws IOException, HttpException { - try { // just to log - boolean customRedirectionNeeded = false; - - try { - method.setFollowRedirects(mFollowRedirects); - } catch (Exception e) { - /* - if (mFollowRedirects) - Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() - + " method, custom redirection will be used if needed"); - */ - customRedirectionNeeded = mFollowRedirects; - } + + /** + * Requests the received method. + * + * Executes the method through the inherited HttpClient.executedMethod(method). + * + * @param method HTTP method request. + */ + @Override + public int executeMethod(HttpMethod method) throws IOException { + try { // Update User Agent HttpParams params = method.getParams(); String userAgent = OwnCloudClientManagerFactory.getUserAgent(); params.setParameter(HttpMethodParams.USER_AGENT, userAgent); - Log_OC.d(TAG + " #" + mInstanceNumber, "REQUEST " + - method.getName() + " " + method.getPath()); - + Log_OC.d(TAG + " #" + mInstanceNumber, "REQUEST " + + method.getName() + " " + method.getPath()); + // logCookiesAtRequest(method.getRequestHeaders(), "before"); // logCookiesAtState("before"); - - int status = super.executeMethod(method); - - if (customRedirectionNeeded) { - status = patchRedirection(status, method); - } + method.setFollowRedirects(false); + + int status = super.executeMethod(method); + + if (mFollowRedirects) { + status = followRedirection(method).getLastStatus(); + } // logCookiesAtRequest(method.getRequestHeaders(), "after"); // logCookiesAtState("after"); // logSetCookiesAtResponse(method.getResponseHeaders()); - - return status; - + + return status; + } catch (IOException e) { - Log_OC.d(TAG + " #" + mInstanceNumber, "Exception occurred", e); - throw e; + //Log_OC.d(TAG + " #" + mInstanceNumber, "Exception occurred", e); + throw e; } } - private int patchRedirection(int status, HttpMethod method) throws HttpException, IOException { + + public RedirectionPath followRedirection(HttpMethod method) throws IOException { int redirectionsCount = 0; + int status = method.getStatusCode(); + RedirectionPath result = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT); while (redirectionsCount < MAX_REDIRECTIONS_COUNT && ( status == HttpStatus.SC_MOVED_PERMANENTLY || status == HttpStatus.SC_MOVED_TEMPORARILY || @@ -254,18 +253,20 @@ public class OwnCloudClient extends HttpClient { Log_OC.d(TAG + " #" + mInstanceNumber, "Location to redirect: " + location.getValue()); + String locationStr = location.getValue(); + result.addLocation(locationStr); + // Release the connection to avoid reach the max number of connections per host // due to it will be set a different url exhaustResponse(method.getResponseBodyAsStream()); method.releaseConnection(); - method.setURI(new URI(location.getValue(), true)); + method.setURI(new URI(locationStr, true)); Header destination = method.getRequestHeader("Destination"); if (destination == null) { destination = method.getRequestHeader("destination"); } if (destination != null) { - String locationStr = location.getValue(); int suffixIndex = locationStr.lastIndexOf( (mCredentials instanceof OwnCloudBearerCredentials) ? AccountUtils.ODAV_PATH : @@ -281,6 +282,7 @@ public class OwnCloudClient extends HttpClient { method.setRequestHeader(destination); } status = super.executeMethod(method); + result.addStatus(status); redirectionsCount++; } else { @@ -288,7 +290,7 @@ public class OwnCloudClient extends HttpClient { status = HttpStatus.SC_NOT_FOUND; } } - return status; + return result; } /** @@ -356,7 +358,10 @@ public class OwnCloudClient extends HttpClient { mFollowRedirects = followRedirects; } - + public boolean getFollowRedirects() { + return mFollowRedirects; + } + private void logCookiesAtRequest(Header[] headers, String when) { int counter = 0; for (int i=0; i= 0; i--) { + if (mStatuses[i] == HttpStatus.SC_MOVED_PERMANENTLY && i <= mLastLocation) { + return mLocations[i]; + } + } + return null; + } + + /** + * @return Count of locations. + */ + public int getRedirectionsCount() { + return mLastLocation + 1; + } + + +} diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index 56492955..bde719ae 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -60,11 +60,11 @@ import com.owncloud.android.lib.common.utils.Log_OC; public class RemoteOperationResult implements Serializable { /** Generated - should be refreshed every time the class changes!! */; - private static final long serialVersionUID = -9003837206000993465L; - - private static final String TAG = "RemoteOperationResult"; - - public enum ResultCode { + private static final long serialVersionUID = 25745846447996048L; + + private static final String TAG = RemoteOperationResult.class.getSimpleName(); + + public enum ResultCode { OK, OK_SSL, OK_NO_SSL, @@ -112,6 +112,7 @@ public class RemoteOperationResult implements Serializable { private ResultCode mCode = ResultCode.UNKNOWN_ERROR; private String mRedirectedLocation; private String mAuthenticate; + private String mLastPermanentLocation = null; private ArrayList mData; @@ -391,4 +392,12 @@ public class RemoteOperationResult implements Serializable { return mAuthenticate; } + public String getLastPermanentLocation() { + return mLastPermanentLocation; + } + + public void setLastPermanentLocation(String lastPermanentLocation) { + mLastPermanentLocation = lastPermanentLocation; + } + } diff --git a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java index 154c8b14..4596594b 100644 --- a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java +++ b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java @@ -31,6 +31,7 @@ import android.content.Context; import android.net.ConnectivityManager; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.network.RedirectionPath; import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -52,7 +53,10 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { private Context mContext; private boolean mSuccessIfAbsent; - + /** Sequence of redirections followed. Available only after executing the operation */ + private RedirectionPath mRedirectionPath = null; + // TODO move to {@link RemoteOperation}, that needs a nice refactoring + /** * Full constructor. Success of the operation will depend upon the value of successIfAbsent. * @@ -75,9 +79,13 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { } RemoteOperationResult result = null; HeadMethod head = null; + boolean previousFollowRedirects = client.getFollowRedirects(); try { head = new HeadMethod(client.getWebdavUri() + WebdavUtils.encodePath(mPath)); - int status = client.executeMethod(head, TIMEOUT, TIMEOUT); + client.setFollowRedirects(false); + client.executeMethod(head, TIMEOUT, TIMEOUT); + mRedirectionPath = client.followRedirection(head); + int status = mRedirectionPath.getLastStatus(); client.exhaustResponse(head.getResponseBodyAsStream()); boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent); @@ -97,6 +105,7 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { } finally { if (head != null) head.releaseConnection(); + client.setFollowRedirects(previousFollowRedirects); } return result; } @@ -109,4 +118,19 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { } + /** + * Gets the sequence of redirections followed during the execution of the operation. + * + * @return Sequence of redirections followed, if any, or NULL if the operation was not executed. + */ + public RedirectionPath getRedirectionPath() { + return mRedirectionPath; + } + + /** + * @return 'True' if the operation was executed and at least one redirection was followed. + */ + public boolean wasRedirected() { + return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0); + } } diff --git a/src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java index 4dc4c2c2..d3af55f5 100644 --- a/src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java @@ -93,7 +93,7 @@ public class RenameRemoteFileOperation extends RemoteOperation { if (noInvalidChars) { try { - + if (mNewName.equals(mOldName)) { return new RemoteOperationResult(ResultCode.OK); } @@ -103,7 +103,7 @@ public class RenameRemoteFileOperation extends RemoteOperation { if (client.existsFile(mNewRemotePath)) { return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE); } - + move = new LocalMoveMethod( client.getWebdavUri() + WebdavUtils.encodePath(mOldRemotePath), client.getWebdavUri() + WebdavUtils.encodePath(mNewRemotePath)); diff --git a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java index dea4fe93..4db29051 100644 --- a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java @@ -72,7 +72,7 @@ public class RemoveRemoteShareOperation extends RemoteOperation { delete = new DeleteMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH + id); delete.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); - + status = client.executeMethod(delete); if(isSuccess(status)) { diff --git a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java index aecc12f3..2b4def0a 100644 --- a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java @@ -103,9 +103,7 @@ public class GetRemoteStatusOperation extends RemoteOperation { ); get.releaseConnection(); get = new GetMethod(redirectedLocation); - status = client.executeMethod( - get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT - ); + status = client.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT); mLatestResult = new RemoteOperationResult( (status == HttpStatus.SC_OK), status,