e33867964e76af4301698ac85f35c5796227c80c
[pub/Android/ownCloud.git] / src / eu / alefzero / owncloud / authenticator / AuthUtils.java
1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
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
19 package eu.alefzero.owncloud.authenticator;
20
21 import java.io.IOException;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.net.UnknownHostException;
25 import org.apache.http.conn.ClientConnectionManager;
26 import org.apache.http.conn.scheme.Scheme;
27 import org.apache.http.conn.scheme.SchemeRegistry;
28
29 import org.apache.http.impl.client.DefaultHttpClient;
30
31 import org.apache.commons.httpclient.auth.BasicScheme;
32 import org.apache.http.HttpHost;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.HttpVersion;
35 import org.apache.http.auth.AuthScope;
36 import org.apache.http.auth.UsernamePasswordCredentials;
37 import org.apache.http.client.ClientProtocolException;
38 import org.apache.http.client.methods.HttpHead;
39 import org.apache.http.conn.params.ConnManagerPNames;
40 import org.apache.http.conn.params.ConnPerRouteBean;
41 import org.apache.http.conn.scheme.PlainSocketFactory;
42 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
43 import org.apache.http.params.BasicHttpParams;
44 import org.apache.http.params.HttpParams;
45 import org.apache.http.params.HttpProtocolParams;
46 import org.apache.http.protocol.BasicHttpContext;
47
48 import eu.alefzero.owncloud.ui.activity.AuthenticatorActivity;
49
50
51 import android.content.Context;
52 import android.os.Handler;
53 import android.util.Log;
54
55 public class AuthUtils {
56 public static final String WEBDAV_PATH_1_2 = "/webdav/owncloud.php";
57 public static final String WEBDAV_PATH_2_0 = "/files/webdav.php";
58 public static final String CARDDAV_PATH_2_0 = "/apps/contacts/carddav.php";
59
60 private static String mResultMsg = "";
61
62 public static boolean authenticate(URL url, String username, String password,
63 Handler handler, Context context) {
64 String strippedPath = url.toString().endsWith("/") ?
65 url.toString().substring(0, url.toString().length()-1) :
66 url.toString();
67 String webdatPath = strippedPath + WEBDAV_PATH_2_0;
68 URL complete_url = null;
69 try {
70 complete_url = new URL(webdatPath);
71 } catch (MalformedURLException e) {
72 // should never happend
73 sendResult(false, handler, context, "URL error");
74 return false;
75 }
76
77 // version 2.0 success
78 if (tryGetWebdav(complete_url, username, password, handler, context)) {
79 sendResult(true, handler, context, complete_url.toString());
80 return true;
81 }
82
83 if (mResultMsg.equals("401")) {
84 sendResult(false, handler, context, "Invalid login or/and password");
85 return false;
86 }
87
88 if (!mResultMsg.equals("404")) {
89 sendResult(false, handler, context, "Server error: " + mResultMsg);
90 return false;
91 }
92
93 webdatPath = strippedPath + WEBDAV_PATH_1_2;
94 try {
95 complete_url = new URL(webdatPath);
96 } catch (MalformedURLException e) {
97 // should never happend
98 sendResult(false, handler, context, "URL error");
99 return false;
100 }
101
102 // version 1.2 success
103 if (tryGetWebdav(complete_url, username, password, handler, context)) {
104 sendResult(true, handler, context, complete_url.toString());
105 return true;
106 }
107
108 if (mResultMsg.equals("401")) {
109 sendResult(false, handler, context, "Invalid login or/and password");
110 return false;
111 }
112
113 if (mResultMsg.equals("404")) {
114 sendResult(false, handler, context, "Wrong path given");
115 return false;
116 }
117
118 sendResult(false, handler, context, "Server error: " + mResultMsg);
119 return false;
120 }
121
122 public static boolean tryGetWebdav(URL url, String username, String pwd,
123 Handler handler, Context context) {
124 SchemeRegistry schemeRegistry = new SchemeRegistry();
125 // http scheme
126 schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
127 // https scheme
128 schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
129
130 HttpParams params = new BasicHttpParams();
131 params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
132 params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30));
133 params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
134 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
135
136 ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
137
138 DefaultHttpClient c = new DefaultHttpClient(cm, params);
139
140 c.getCredentialsProvider().setCredentials(
141 new AuthScope(url.getHost(), (url.getPort() == -1)?80:url.getPort()),
142 new UsernamePasswordCredentials(username, pwd));
143
144 BasicHttpContext localcontext = new BasicHttpContext();
145 BasicScheme basicAuth = new BasicScheme();
146
147 localcontext.setAttribute("preemptive-auth", basicAuth);
148 HttpHost targetHost = new HttpHost(url.getHost(), (url.getPort() == -1)
149 ? 80
150 : url.getPort(), (url.getProtocol().equals("https")) ? "https" : "http");
151 HttpHead httpget = new HttpHead(url.toString());
152 httpget.setHeader("Host", url.getHost());
153 HttpResponse response = null;
154 try {
155 response = c.execute(targetHost, httpget, localcontext);
156 } catch (ClientProtocolException e1) {
157 sendResult(false, handler, context, "Protocol error: "
158 + e1.getLocalizedMessage());
159 return false;
160 } catch (UnknownHostException e1) {
161 mResultMsg = "Unknowh host: " + e1.getLocalizedMessage();
162 return false;
163 } catch (IOException e1) {
164 mResultMsg = "Error: " + e1.getLocalizedMessage();
165 return false;
166 }
167 String status = response.getStatusLine().toString();
168
169 status = status.split(" ")[1];
170 Log.i("AuthUtils", "Status returned: " + status);
171 if (status.equals("200")) {
172 return true;
173 } else if (status.equals("404")) {
174 mResultMsg = "404";
175 return false;
176 } else if (status.equals("401")) {
177 mResultMsg = "401";
178 return false;
179 }
180 mResultMsg = status;
181 return false;
182 }
183
184 public static Thread performOnBackgroundThread(final Runnable r) {
185 final Thread t = new Thread() {
186 @Override
187 public void run() {
188 try {
189 r.run();
190 } finally {}
191 }
192 };
193 t.start();
194 return t;
195 }
196
197 public static void sendResult(final Boolean result,
198 final Handler handler,
199 final Context context,
200 final String message) {
201 if (handler == null || context == null) {
202 return;
203 }
204 handler.post(new Runnable() {
205 public void run() {
206 ((AuthenticatorActivity) context).onAuthenticationResult(result, message);
207 }
208 });
209 }
210
211 public static Thread attemptAuth(final URL url, final String username,
212 final String password, final Handler handler,
213 final Context context) {
214 final Runnable r = new Runnable() {
215
216 public void run() {
217 authenticate(url, username, password, handler, context);
218 }
219 };
220 return performOnBackgroundThread(r);
221 }
222 }