Server certificates improvements: fixed problems in devices with OpenSSL implementati...
[pub/Android/ownCloud.git] / src / com / owncloud / android / authenticator / ConnectionCheckerRunnable.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012 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 com.owncloud.android.authenticator;
20
21 import java.io.IOException;
22 import java.net.MalformedURLException;
23 import java.net.SocketException;
24 import java.net.SocketTimeoutException;
25 import java.net.UnknownHostException;
26
27 import javax.net.ssl.SSLException;
28 import javax.net.ssl.SSLPeerUnverifiedException;
29
30 import org.apache.commons.httpclient.ConnectTimeoutException;
31 import org.apache.commons.httpclient.HttpException;
32 import org.apache.commons.httpclient.HttpStatus;
33 import org.apache.commons.httpclient.methods.GetMethod;
34 import org.json.JSONException;
35 import org.json.JSONObject;
36
37 import com.owncloud.android.AccountUtils;
38 import com.owncloud.android.authenticator.OnConnectCheckListener.ResultType;
39 import com.owncloud.android.network.OwnCloudClientUtils;
40 import com.owncloud.android.utils.OwnCloudVersion;
41
42 import eu.alefzero.webdav.WebdavClient;
43 import android.content.Context;
44 import android.net.ConnectivityManager;
45 import android.net.Uri;
46 import android.os.Handler;
47 import android.util.Log;
48
49 public class ConnectionCheckerRunnable implements Runnable {
50
51 /** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs. */
52 public static final int TRY_CONNECTION_TIMEOUT = 5000;
53
54 private static final String TAG = "ConnectionCheckerRunnable";
55 private OnConnectCheckListener mListener;
56 private String mUrl;
57 private Handler mHandler;
58 private ResultType mLatestResult;
59 private Context mContext;
60 private OwnCloudVersion mOCVersion;
61
62 public void setListener(OnConnectCheckListener listener, Handler handler) {
63 mListener = listener;
64 mHandler = handler;
65 }
66
67 public ConnectionCheckerRunnable(String url, Context context) {
68 mListener = null;
69 mHandler = null;
70 mUrl = url;
71 mContext = context;
72 mOCVersion = null;
73 }
74
75 @Override
76 public void run() {
77
78 if (!isOnline()) {
79 postResult(ResultType.NO_NETWORK_CONNECTION);
80 return;
81 }
82 if (mUrl.startsWith("http://") || mUrl.startsWith("https://")) {
83 mLatestResult = (mUrl.startsWith("https://"))? ResultType.OK_SSL : ResultType.OK_NO_SSL;
84 tryConnection(mUrl + AccountUtils.STATUS_PATH);
85 postResult(mLatestResult);
86 } else {
87 if (tryConnection("https://" + mUrl + AccountUtils.STATUS_PATH)) {
88 postResult(ResultType.OK_SSL);
89 return;
90 }
91 Log.d(TAG,
92 "establishing secure connection failed, trying non secure connection");
93
94 if (tryConnection("http://" + mUrl + AccountUtils.STATUS_PATH)) {
95 postResult(ResultType.OK_NO_SSL);
96 return;
97 }
98 postResult(mLatestResult);
99 }
100 }
101
102 public OwnCloudVersion getDiscoveredVersion() {
103 return mOCVersion;
104 }
105
106 private boolean tryConnection(String urlSt) {
107 boolean retval = false;
108 GetMethod get = null;
109 try {
110 WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(urlSt), mContext);
111 get = new GetMethod(urlSt);
112 int status = wc.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
113 String response = get.getResponseBodyAsString();
114 switch (status) {
115 case HttpStatus.SC_OK: {
116 JSONObject json = new JSONObject(response);
117 if (!json.getBoolean("installed")) {
118 mLatestResult = ResultType.INSTANCE_NOT_CONFIGURED;
119 break;
120 }
121 mOCVersion = new OwnCloudVersion(json.getString("version"));
122 if (!mOCVersion.isVersionValid()) {
123 mLatestResult = ResultType.BAD_OC_VERSION;
124 break;
125 }
126 retval = true;
127 break;
128 }
129 case HttpStatus.SC_NOT_FOUND:
130 mLatestResult = ResultType.FILE_NOT_FOUND;
131 break;
132 case HttpStatus.SC_INTERNAL_SERVER_ERROR:
133 mLatestResult = ResultType.INSTANCE_NOT_CONFIGURED;
134 break;
135 default:
136 mLatestResult = ResultType.UNKNOWN_ERROR;
137 Log.e(TAG, "Not handled status received from server: " + status);
138 }
139
140 } catch (JSONException e) {
141 mLatestResult = ResultType.INSTANCE_NOT_CONFIGURED;
142 Log.e(TAG, "JSON exception while trying connection (instance not configured) ", e);
143
144 } catch (SocketException e) {
145 mLatestResult = ResultType.WRONG_CONNECTION;
146 Log.e(TAG, "Socket exception while trying connection", e);
147
148 } catch (SocketTimeoutException e) {
149 mLatestResult = ResultType.TIMEOUT;
150 Log.e(TAG, "Socket timeout exception while trying connection", e);
151
152 } catch (MalformedURLException e) {
153 mLatestResult = ResultType.INCORRECT_ADDRESS;
154 Log.e(TAG, "Connect exception while trying connection", e);
155
156 } catch (UnknownHostException e) {
157 mLatestResult = ResultType.HOST_NOT_AVAILABLE;
158 Log.e(TAG, "Unknown host exception while trying connection", e);
159
160 } catch (SSLPeerUnverifiedException e) { // specially meaningful SSLException
161 mLatestResult = ResultType.SSL_UNVERIFIED_SERVER;
162 Log.e(TAG, "SSL Peer Unverified exception while trying connection", e);
163
164 } catch (SSLException e) {
165 mLatestResult = ResultType.SSL_INIT_ERROR;
166 Log.e(TAG, "SSL exception while trying connection", e);
167
168 } catch (ConnectTimeoutException e) { // timeout specific exception from org.apache.commons.httpclient
169 mLatestResult = ResultType.TIMEOUT;
170 Log.e(TAG, "Socket timeout exception while trying connection", e);
171
172 } catch (HttpException e) { // other specific exceptions from org.apache.commons.httpclient
173 mLatestResult = ResultType.UNKNOWN_ERROR;
174 Log.e(TAG, "HTTP exception while trying connection", e);
175
176 } catch (IOException e) { // UnkownsServiceException, and any other transport exceptions that could occur
177 mLatestResult = ResultType.UNKNOWN_ERROR;
178 Log.e(TAG, "I/O exception while trying connection", e);
179
180 } catch (Exception e) {
181 mLatestResult = ResultType.UNKNOWN_ERROR;
182 Log.e(TAG, "Unexpected exception while trying connection", e);
183
184 } finally {
185 if (get != null)
186 get.releaseConnection();
187 }
188
189 return retval;
190 }
191
192 private boolean isOnline() {
193 ConnectivityManager cm = (ConnectivityManager) mContext
194 .getSystemService(Context.CONNECTIVITY_SERVICE);
195 return cm != null && cm.getActiveNetworkInfo() != null
196 && cm.getActiveNetworkInfo().isConnectedOrConnecting();
197 }
198
199 private void postResult(final ResultType result) {
200 if (mHandler != null && mListener != null) {
201 mHandler.post(new Runnable() {
202 @Override
203 public void run() {
204 mListener.onConnectionCheckResult(result);
205 }
206 });
207 }
208 }
209
210 }