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

Merge branch 'develop' into forbidden_characters_from_server

Conflicts:
	src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java
	src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java
This commit is contained in:
masensio 2015-06-15 14:41:27 +02:00
commit 060ca75f17
7 changed files with 212 additions and 48 deletions

View File

@ -49,6 +49,7 @@ 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;
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
@ -56,7 +57,7 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
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;
@ -171,13 +172,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 {
@ -194,55 +195,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 ||
@ -257,18 +256,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 :
@ -284,6 +285,7 @@ public class OwnCloudClient extends HttpClient {
method.setRequestHeader(destination);
}
status = super.executeMethod(method);
result.addStatus(status);
redirectionsCount++;
} else {
@ -291,7 +293,7 @@ public class OwnCloudClient extends HttpClient {
status = HttpStatus.SC_NOT_FOUND;
}
}
return status;
return result;
}
/**
@ -359,7 +361,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<headers.length; i++) {

View File

@ -0,0 +1,127 @@
/* ownCloud Android Library is available under MIT license
*
* @author David A. Velasco
*
* Copyright (C) 2015 ownCloud Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package com.owncloud.android.lib.common.network;
import org.apache.http.HttpStatus;
import java.util.Arrays;
/**
* Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
* {@link com.owncloud.android.lib.common.operations.RemoteOperation}, and the status codes corresponding to all
* of them.
*
* The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
* the maximum length of redirections allowed by the {@link com.owncloud.android.lib.common.OwnCloudClient} instance
* that ran the operation.
*
* If no redirection was followed, the last (and first) status code contained corresponds to the original URL in the
* request.
*/
public class RedirectionPath {
private int[] mStatuses = null;
private int mLastStatus = -1;
private String[] mLocations = null;
private int mLastLocation = -1;
private int maxRedirections;
/**
* Public constructor.
*
* @param status Status code resulting of executing a request on the original URL.
* @param maxRedirections Maximum number of redirections that will be contained.
* @throws IllegalArgumentException If 'maxRedirections' is < 0
*/
public RedirectionPath(int status, int maxRedirections) {
if (maxRedirections < 0) {
throw new IllegalArgumentException("maxRedirections MUST BE zero or greater");
}
mStatuses = new int[maxRedirections + 1];
Arrays.fill(mStatuses, -1);
mStatuses[++mLastStatus] = status;
}
/**
* Adds a new location URL to the list of followed redirections.
*
* @param location URL extracted from a 'Location' header in a redirection.
*/
public void addLocation(String location) {
if (mLocations == null) {
mLocations = new String[mStatuses.length - 1];
}
if (mLastLocation < mLocations.length - 1) {
mLocations[++mLastLocation] = location;
}
}
/**
* Adds a new status code to the list of status corresponding to followed redirections.
*
* @param status Status code from the response of another followed redirection.
*/
public void addStatus(int status) {
if (mLastStatus < mStatuses.length - 1) {
mStatuses[++mLastStatus] = status;
}
}
/**
* @return Last status code saved.
*/
public int getLastStatus() {
return mStatuses[mLastStatus];
}
/**
* @return Last location followed corresponding to a permanent redirection (status code 301).
*/
public String getLastPermanentLocation() {
for (int i = mLastStatus; i >= 0; i--) {
if (mStatuses[i] == HttpStatus.SC_MOVED_PERMANENTLY && i <= mLastLocation) {
return mLocations[i];
}
}
return null;
}
/**
* @return Count of locations.
*/
public int getRedirectionsCount() {
return mLastLocation + 1;
}
}

View File

@ -62,11 +62,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 = -4184015692120731701L;
private static final long serialVersionUID = -1909603208238358633L;
private static final String TAG = RemoteOperationResult.class.getSimpleName();
public enum ResultCode {
public enum ResultCode {
OK,
OK_SSL,
OK_NO_SSL,
@ -115,6 +115,7 @@ public class RemoteOperationResult implements Serializable {
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
private String mRedirectedLocation;
private String mAuthenticate;
private String mLastPermanentLocation = null;
private ArrayList<Object> mData;
@ -433,4 +434,12 @@ public class RemoteOperationResult implements Serializable {
return mAuthenticate;
}
public String getLastPermanentLocation() {
return mLastPermanentLocation;
}
public void setLastPermanentLocation(String lastPermanentLocation) {
mLastPermanentLocation = lastPermanentLocation;
}
}

View File

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

View File

@ -131,6 +131,7 @@ public class RenameRemoteFileOperation extends RemoteOperation {
if (move != null)
move.releaseConnection();
}
} else {
result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
}

View File

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

View File

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