1 /* ownCloud Android client application 
   2  *   Copyright (C) 2011  Bartek Przybylski 
   3  *   Copyright (C) 2012-2013 ownCloud Inc. 
   5  *   This program is free software: you can redistribute it and/or modify 
   6  *   it under the terms of the GNU General Public License version 2, 
   7  *   as published by the Free Software Foundation. 
   9  *   This program is distributed in the hope that it will be useful, 
  10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  12  *   GNU General Public License for more details. 
  14  *   You should have received a copy of the GNU General Public License 
  15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  19 package eu
.alefzero
.webdav
; 
  21 import java
.io
.IOException
; 
  22 import java
.io
.InputStream
; 
  23 import java
.util
.ArrayList
; 
  24 import java
.util
.List
; 
  26 import org
.apache
.commons
.httpclient
.Credentials
; 
  27 import org
.apache
.commons
.httpclient
.Header
; 
  28 import org
.apache
.commons
.httpclient
.HttpClient
; 
  29 import org
.apache
.commons
.httpclient
.HttpConnectionManager
; 
  30 import org
.apache
.commons
.httpclient
.HttpException
; 
  31 import org
.apache
.commons
.httpclient
.HttpMethod
; 
  32 import org
.apache
.commons
.httpclient
.HttpMethodBase
; 
  33 import org
.apache
.commons
.httpclient
.HttpVersion
; 
  34 import org
.apache
.commons
.httpclient
.URI
; 
  35 import org
.apache
.commons
.httpclient
.UsernamePasswordCredentials
; 
  36 import org
.apache
.commons
.httpclient
.auth
.AuthPolicy
; 
  37 import org
.apache
.commons
.httpclient
.auth
.AuthScope
; 
  38 import org
.apache
.commons
.httpclient
.cookie
.CookiePolicy
; 
  39 import org
.apache
.commons
.httpclient
.methods
.HeadMethod
; 
  40 import org
.apache
.commons
.httpclient
.params
.HttpMethodParams
; 
  41 import org
.apache
.http
.HttpStatus
; 
  42 import org
.apache
.http
.params
.CoreProtocolPNames
; 
  44 import com
.owncloud
.android
.Log_OC
; 
  45 import com
.owncloud
.android
.MainApp
; 
  46 import com
.owncloud
.android
.network
.BearerAuthScheme
; 
  47 import com
.owncloud
.android
.network
.BearerCredentials
; 
  51 import android
.net
.Uri
; 
  53 public class WebdavClient 
extends HttpClient 
{ 
  54     private static final int MAX_REDIRECTIONS_COUNT 
= 3; 
  57     private Credentials mCredentials
; 
  58     private boolean mFollowRedirects
; 
  59     private String mSsoSessionCookie
; 
  60     private String mAuthTokenType
; 
  61     final private static String TAG 
= "WebdavClient"; 
  62     public static final String USER_AGENT 
= "Android-ownCloud"; 
  64     static private byte[] sExhaustBuffer 
= new byte[1024]; 
  69     public WebdavClient(HttpConnectionManager connectionMgr
) { 
  71         Log_OC
.d(TAG
, "Creating WebdavClient"); 
  72         getParams().setParameter(HttpMethodParams
.USER_AGENT
, USER_AGENT
); 
  73         getParams().setParameter(CoreProtocolPNames
.PROTOCOL_VERSION
, HttpVersion
.HTTP_1_1
); 
  74         mFollowRedirects 
= true
; 
  75         mSsoSessionCookie 
= null
; 
  76         mAuthTokenType 
= MainApp
.getAuthTokenTypePass(); 
  79     public void setBearerCredentials(String accessToken
) { 
  80         AuthPolicy
.registerAuthScheme(BearerAuthScheme
.AUTH_POLICY
, BearerAuthScheme
.class); 
  82         List
<String
> authPrefs 
= new ArrayList
<String
>(1); 
  83         authPrefs
.add(BearerAuthScheme
.AUTH_POLICY
); 
  84         getParams().setParameter(AuthPolicy
.AUTH_SCHEME_PRIORITY
, authPrefs
);         
  86         mCredentials 
= new BearerCredentials(accessToken
); 
  87         getState().setCredentials(AuthScope
.ANY
, mCredentials
); 
  88         mSsoSessionCookie 
= null
; 
  89         mAuthTokenType 
= MainApp
.getAuthTokenTypeAccessToken(); 
  92     public void setBasicCredentials(String username
, String password
) { 
  93         List
<String
> authPrefs 
= new ArrayList
<String
>(1); 
  94         authPrefs
.add(AuthPolicy
.BASIC
); 
  95         getParams().setParameter(AuthPolicy
.AUTH_SCHEME_PRIORITY
, authPrefs
);         
  97         getParams().setAuthenticationPreemptive(true
); 
  98         mCredentials 
= new UsernamePasswordCredentials(username
, password
); 
  99         getState().setCredentials(AuthScope
.ANY
, mCredentials
); 
 100         mSsoSessionCookie 
= null
; 
 101         mAuthTokenType 
= MainApp
.getAuthTokenTypePass(); 
 104     public void setSsoSessionCookie(String accessToken
) { 
 105         getParams().setAuthenticationPreemptive(false
); 
 106         getParams().setCookiePolicy(CookiePolicy
.IGNORE_COOKIES
); 
 107         mSsoSessionCookie 
= accessToken
; 
 109         mAuthTokenType 
= MainApp
.getAuthTokenTypeSamlSessionCookie(); 
 114      * Check if a file exists in the OC server 
 116      * TODO replace with ExistenceOperation 
 118      * @return              'true' if the file exists; 'false' it doesn't exist 
 119      * @throws  Exception   When the existence could not be determined 
 121     public boolean existsFile(String path
) throws IOException
, HttpException 
{ 
 122         HeadMethod head 
= new HeadMethod(mUri
.toString() + WebdavUtils
.encodePath(path
)); 
 124             int status 
= executeMethod(head
); 
 125             Log_OC
.d(TAG
, "HEAD to " + path 
+ " finished with HTTP status " + status 
+ ((status 
!= HttpStatus
.SC_OK
)?
"(FAIL)":"")); 
 126             exhaustResponse(head
.getResponseBodyAsStream()); 
 127             return (status 
== HttpStatus
.SC_OK
); 
 130             head
.releaseConnection();    // let the connection available for other methods 
 135      * Requests the received method with the received timeout (milliseconds). 
 137      * Executes the method through the inherited HttpClient.executedMethod(method). 
 139      * Sets the socket and connection timeouts only for the method received. 
 141      * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default' 
 143      * @param method            HTTP method request. 
 144      * @param readTimeout       Timeout to set for data reception 
 145      * @param conntionTimout    Timeout to set for connection establishment 
 147     public int executeMethod(HttpMethodBase method
, int readTimeout
, int connectionTimeout
) throws HttpException
, IOException 
{ 
 148         int oldSoTimeout 
= getParams().getSoTimeout(); 
 149         int oldConnectionTimeout 
= getHttpConnectionManager().getParams().getConnectionTimeout(); 
 151             if (readTimeout 
>= 0) {  
 152                 method
.getParams().setSoTimeout(readTimeout
);   // this should be enough... 
 153                 getParams().setSoTimeout(readTimeout
);          // ... but this looks like necessary for HTTPS 
 155             if (connectionTimeout 
>= 0) { 
 156                 getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout
); 
 158             return executeMethod(method
); 
 160             getParams().setSoTimeout(oldSoTimeout
); 
 161             getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout
); 
 167     public int executeMethod(HttpMethod method
) throws IOException
, HttpException 
{ 
 168         boolean customRedirectionNeeded 
= false
; 
 170             method
.setFollowRedirects(mFollowRedirects
); 
 171         } catch (Exception e
) { 
 172             if (mFollowRedirects
) Log_OC
.d(TAG
, "setFollowRedirects failed for " + method
.getName() + " method, custom redirection will be used"); 
 173             customRedirectionNeeded 
= mFollowRedirects
; 
 175         if (mSsoSessionCookie 
!= null 
&& mSsoSessionCookie
.length() > 0) { 
 176             method
.setRequestHeader("Cookie", mSsoSessionCookie
); 
 178         int status 
= super.executeMethod(method
); 
 179         int redirectionsCount 
= 0; 
 180         while (customRedirectionNeeded 
&& 
 181                 redirectionsCount 
< MAX_REDIRECTIONS_COUNT 
&& 
 182                 (   status 
== HttpStatus
.SC_MOVED_PERMANENTLY 
||  
 183                     status 
== HttpStatus
.SC_MOVED_TEMPORARILY 
|| 
 184                     status 
== HttpStatus
.SC_TEMPORARY_REDIRECT
) 
 187             Header location 
= method
.getResponseHeader("Location"); 
 188             if (location 
!= null
) { 
 189                 Log_OC
.d(TAG
,  "Location to redirect: " + location
.getValue()); 
 190                 method
.setURI(new URI(location
.getValue(), true
)); 
 191                 status 
= super.executeMethod(method
); 
 195                 Log_OC
.d(TAG
,  "No location to redirect!"); 
 196                 status 
= HttpStatus
.SC_NOT_FOUND
; 
 205      * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation. 
 207      * @param responseBodyAsStream      InputStream with the HTTP response to exhaust. 
 209     public void exhaustResponse(InputStream responseBodyAsStream
) { 
 210         if (responseBodyAsStream 
!= null
) { 
 212                 while (responseBodyAsStream
.read(sExhaustBuffer
) >= 0); 
 213                 responseBodyAsStream
.close(); 
 215             } catch (IOException io
) { 
 216                 Log_OC
.e(TAG
, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io
); 
 222      * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client. 
 224     public void setDefaultTimeouts(int defaultDataTimeout
, int defaultConnectionTimeout
) { 
 225             getParams().setSoTimeout(defaultDataTimeout
); 
 226             getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout
); 
 230      * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs 
 233     public void setBaseUri(Uri uri
) { 
 237     public Uri 
getBaseUri() { 
 241     public final Credentials 
getCredentials() { 
 245     public final String 
getSsoSessionCookie() { 
 246         return mSsoSessionCookie
; 
 249     public void setFollowRedirects(boolean followRedirects
) { 
 250         mFollowRedirects 
= followRedirects
; 
 253     public String 
getAuthTokenType() { 
 254         return mAuthTokenType
;