Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 060ca75f authored by masensio's avatar masensio
Browse files

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
parents 4ca0ff22 639cb7ea
Loading
Loading
Loading
Loading
+45 −40
Original line number Diff line number Diff line
@@ -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;
    
@@ -176,8 +177,8 @@ public class OwnCloudClient extends HttpClient {
     * @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 {
@@ -196,22 +197,16 @@ public class OwnCloudClient extends HttpClient {
    }


    /**
     * 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, HttpException {
        try {	// just to log 
	        boolean customRedirectionNeeded = false;
	        
    public int executeMethod(HttpMethod method) throws IOException {
        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;
	        }

            // Update User Agent
            HttpParams params = method.getParams();
            String userAgent = OwnCloudClientManagerFactory.getUserAgent();
@@ -222,11 +217,12 @@ public class OwnCloudClient extends HttpClient {

//	        logCookiesAtRequest(method.getRequestHeaders(), "before");
//	        logCookiesAtState("before");
            method.setFollowRedirects(false);

            int status = super.executeMethod(method);

	        if (customRedirectionNeeded) {
	        	status = patchRedirection(status, method);
            if (mFollowRedirects) {
                status = followRedirection(method).getLastStatus();
            }

//	        logCookiesAtRequest(method.getRequestHeaders(), "after");
@@ -236,13 +232,16 @@ public class OwnCloudClient extends HttpClient {
            return status;

        } catch (IOException e) {
        	Log_OC.d(TAG + " #" + mInstanceNumber, "Exception occurred", 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,6 +361,9 @@ public class OwnCloudClient extends HttpClient {
        mFollowRedirects = followRedirects;
    }

    public boolean getFollowRedirects() {
        return mFollowRedirects;
    }

	private void logCookiesAtRequest(Header[] headers, String when) {
        int counter = 0;
+127 −0
Original line number Diff line number Diff line
/* 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;
    }


}
+11 −2
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ 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();

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

}
+26 −2
Original line number Diff line number Diff line
@@ -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,6 +53,9 @@ 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);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ public class RenameRemoteFileOperation extends RemoteOperation {
                if (move != null)
                    move.releaseConnection();
            }

        } else {
        	result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
        }
Loading