WebdavClient.java 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /* ownCloud Android client application
  2. * Copyright (C) 2011 Bartek Przybylski
  3. * Copyright (C) 2012-2013 ownCloud Inc.
  4. *
  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.
  8. *
  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.
  13. *
  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/>.
  16. *
  17. */
  18. package com.owncloud.android.network.webdav;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import org.apache.commons.httpclient.Credentials;
  24. import org.apache.commons.httpclient.Header;
  25. import org.apache.commons.httpclient.HttpClient;
  26. import org.apache.commons.httpclient.HttpConnectionManager;
  27. import org.apache.commons.httpclient.HttpException;
  28. import org.apache.commons.httpclient.HttpMethod;
  29. import org.apache.commons.httpclient.HttpMethodBase;
  30. import org.apache.commons.httpclient.HttpVersion;
  31. import org.apache.commons.httpclient.URI;
  32. import org.apache.commons.httpclient.UsernamePasswordCredentials;
  33. import org.apache.commons.httpclient.auth.AuthPolicy;
  34. import org.apache.commons.httpclient.auth.AuthScope;
  35. import org.apache.commons.httpclient.cookie.CookiePolicy;
  36. import org.apache.commons.httpclient.methods.HeadMethod;
  37. import org.apache.commons.httpclient.params.HttpMethodParams;
  38. import org.apache.http.HttpStatus;
  39. import org.apache.http.params.CoreProtocolPNames;
  40. import com.owncloud.android.Log_OC;
  41. import com.owncloud.android.MainApp;
  42. import com.owncloud.android.network.BearerAuthScheme;
  43. import com.owncloud.android.network.BearerCredentials;
  44. import android.net.Uri;
  45. public class WebdavClient extends HttpClient {
  46. private static final int MAX_REDIRECTIONS_COUNT = 3;
  47. private Uri mUri;
  48. private Credentials mCredentials;
  49. private boolean mFollowRedirects;
  50. private String mSsoSessionCookie;
  51. private String mAuthTokenType;
  52. final private static String TAG = "WebdavClient";
  53. public static final String USER_AGENT = "Android-ownCloud";
  54. static private byte[] sExhaustBuffer = new byte[1024];
  55. /**
  56. * Constructor
  57. */
  58. public WebdavClient(HttpConnectionManager connectionMgr) {
  59. super(connectionMgr);
  60. Log_OC.d(TAG, "Creating WebdavClient");
  61. getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
  62. getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
  63. mFollowRedirects = true;
  64. mSsoSessionCookie = null;
  65. mAuthTokenType = MainApp.getAuthTokenTypePass();
  66. }
  67. public void setBearerCredentials(String accessToken) {
  68. AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
  69. List<String> authPrefs = new ArrayList<String>(1);
  70. authPrefs.add(BearerAuthScheme.AUTH_POLICY);
  71. getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
  72. mCredentials = new BearerCredentials(accessToken);
  73. getState().setCredentials(AuthScope.ANY, mCredentials);
  74. mSsoSessionCookie = null;
  75. mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();
  76. }
  77. public void setBasicCredentials(String username, String password) {
  78. List<String> authPrefs = new ArrayList<String>(1);
  79. authPrefs.add(AuthPolicy.BASIC);
  80. getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
  81. getParams().setAuthenticationPreemptive(true);
  82. mCredentials = new UsernamePasswordCredentials(username, password);
  83. getState().setCredentials(AuthScope.ANY, mCredentials);
  84. mSsoSessionCookie = null;
  85. mAuthTokenType = MainApp.getAuthTokenTypePass();
  86. }
  87. public void setSsoSessionCookie(String accessToken) {
  88. getParams().setAuthenticationPreemptive(false);
  89. getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
  90. mSsoSessionCookie = accessToken;
  91. mCredentials = null;
  92. mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();
  93. }
  94. /**
  95. * Check if a file exists in the OC server
  96. *
  97. * TODO replace with ExistenceOperation
  98. *
  99. * @return 'true' if the file exists; 'false' it doesn't exist
  100. * @throws Exception When the existence could not be determined
  101. */
  102. public boolean existsFile(String path) throws IOException, HttpException {
  103. HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
  104. try {
  105. int status = executeMethod(head);
  106. Log_OC.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
  107. exhaustResponse(head.getResponseBodyAsStream());
  108. return (status == HttpStatus.SC_OK);
  109. } finally {
  110. head.releaseConnection(); // let the connection available for other methods
  111. }
  112. }
  113. /**
  114. * Requests the received method with the received timeout (milliseconds).
  115. *
  116. * Executes the method through the inherited HttpClient.executedMethod(method).
  117. *
  118. * Sets the socket and connection timeouts only for the method received.
  119. *
  120. * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
  121. *
  122. * @param method HTTP method request.
  123. * @param readTimeout Timeout to set for data reception
  124. * @param conntionTimout Timeout to set for connection establishment
  125. */
  126. public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
  127. int oldSoTimeout = getParams().getSoTimeout();
  128. int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
  129. try {
  130. if (readTimeout >= 0) {
  131. method.getParams().setSoTimeout(readTimeout); // this should be enough...
  132. getParams().setSoTimeout(readTimeout); // ... but this looks like necessary for HTTPS
  133. }
  134. if (connectionTimeout >= 0) {
  135. getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
  136. }
  137. return executeMethod(method);
  138. } finally {
  139. getParams().setSoTimeout(oldSoTimeout);
  140. getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
  141. }
  142. }
  143. @Override
  144. public int executeMethod(HttpMethod method) throws IOException, HttpException {
  145. boolean customRedirectionNeeded = false;
  146. try {
  147. method.setFollowRedirects(mFollowRedirects);
  148. } catch (Exception e) {
  149. //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
  150. customRedirectionNeeded = mFollowRedirects;
  151. }
  152. if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
  153. method.setRequestHeader("Cookie", mSsoSessionCookie);
  154. }
  155. int status = super.executeMethod(method);
  156. int redirectionsCount = 0;
  157. while (customRedirectionNeeded &&
  158. redirectionsCount < MAX_REDIRECTIONS_COUNT &&
  159. ( status == HttpStatus.SC_MOVED_PERMANENTLY ||
  160. status == HttpStatus.SC_MOVED_TEMPORARILY ||
  161. status == HttpStatus.SC_TEMPORARY_REDIRECT)
  162. ) {
  163. Header location = method.getResponseHeader("Location");
  164. if (location != null) {
  165. Log_OC.d(TAG, "Location to redirect: " + location.getValue());
  166. method.setURI(new URI(location.getValue(), true));
  167. status = super.executeMethod(method);
  168. redirectionsCount++;
  169. } else {
  170. Log_OC.d(TAG, "No location to redirect!");
  171. status = HttpStatus.SC_NOT_FOUND;
  172. }
  173. }
  174. return status;
  175. }
  176. /**
  177. * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
  178. *
  179. * @param responseBodyAsStream InputStream with the HTTP response to exhaust.
  180. */
  181. public void exhaustResponse(InputStream responseBodyAsStream) {
  182. if (responseBodyAsStream != null) {
  183. try {
  184. while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
  185. responseBodyAsStream.close();
  186. } catch (IOException io) {
  187. Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
  188. }
  189. }
  190. }
  191. /**
  192. * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
  193. */
  194. public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
  195. getParams().setSoTimeout(defaultDataTimeout);
  196. getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
  197. }
  198. /**
  199. * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
  200. * @param uri
  201. */
  202. public void setBaseUri(Uri uri) {
  203. mUri = uri;
  204. }
  205. public Uri getBaseUri() {
  206. return mUri;
  207. }
  208. public final Credentials getCredentials() {
  209. return mCredentials;
  210. }
  211. public final String getSsoSessionCookie() {
  212. return mSsoSessionCookie;
  213. }
  214. public void setFollowRedirects(boolean followRedirects) {
  215. mFollowRedirects = followRedirects;
  216. }
  217. public String getAuthTokenType() {
  218. return mAuthTokenType;
  219. }
  220. }