From: David A. Velasco
Date: Wed, 5 Sep 2012 11:46:30 +0000 (+0200)
Subject: SSL connections update: notice about untrusted certificates and allow the user save...
X-Git-Tag: oc-android-1.4.3~189
X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/48f13c8adc5c4b9bc4ca96bf13939a7d7cfae562?ds=inline
SSL connections update: notice about untrusted certificates and allow the user save them as reliable
---
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 151d633a..3d0bc2e2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,8 +17,8 @@
along with this program. If not, see .
-->
+ android:versionCode="103009"
+ android:versionName="1.3.9" xmlns:android="http://schemas.android.com/apk/res/android">
diff --git a/res/layout/ssl_validator_layout.xml b/res/layout/ssl_validator_layout.xml
new file mode 100644
index 00000000..9331b290
--- /dev/null
+++ b/res/layout/ssl_validator_layout.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0c978f1e..cd55ee86 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -183,4 +183,15 @@
"Unexpected problem ; please, try other app to select the file"No file was selected
+
+ Warning
+ The identity of the site could not be verified
+ - The server certificate is not trusted
+ - The server certificate expired
+ - The server certificate is too young
+ - The URL does not match the host name in the certificate
+ Do you want to trust this certificate anyway?
+ The certificate could not be saved
+
+ This is a placeholder
diff --git a/src/com/owncloud/android/Uploader.java b/src/com/owncloud/android/Uploader.java
index 6f650d7b..0505ac9c 100644
--- a/src/com/owncloud/android/Uploader.java
+++ b/src/com/owncloud/android/Uploader.java
@@ -30,7 +30,7 @@ import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
diff --git a/src/com/owncloud/android/authenticator/AuthenticationRunnable.java b/src/com/owncloud/android/authenticator/AuthenticationRunnable.java
index f40701f4..ac547f8f 100644
--- a/src/com/owncloud/android/authenticator/AuthenticationRunnable.java
+++ b/src/com/owncloud/android/authenticator/AuthenticationRunnable.java
@@ -22,10 +22,11 @@ import java.net.URL;
import org.apache.commons.httpclient.HttpStatus;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import eu.alefzero.webdav.WebdavClient;
+import android.content.Context;
import android.net.Uri;
import android.os.Handler;
@@ -36,12 +37,14 @@ public class AuthenticationRunnable implements Runnable {
private URL mUrl;
private String mUsername;
private String mPassword;
+ private Context mContext;
- public AuthenticationRunnable(URL url, String username, String password) {
+ public AuthenticationRunnable(URL url, String username, String password, Context context) {
mListener = null;
mUrl = url;
mUsername = username;
mPassword = password;
+ mContext = context;
}
public void setOnAuthenticationResultListener(
@@ -54,7 +57,7 @@ public class AuthenticationRunnable implements Runnable {
public void run() {
Uri uri;
uri = Uri.parse(mUrl.toString());
- WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(uri, mUsername, mPassword);
+ WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(uri, mUsername, mPassword, mContext);
int login_result = wdc.tryToLogin();
switch (login_result) {
case HttpStatus.SC_OK:
diff --git a/src/com/owncloud/android/authenticator/ConnectionCheckOperation.java b/src/com/owncloud/android/authenticator/ConnectionCheckOperation.java
new file mode 100644
index 00000000..de110516
--- /dev/null
+++ b/src/com/owncloud/android/authenticator/ConnectionCheckOperation.java
@@ -0,0 +1,137 @@
+/* ownCloud Android client application
+ * Copyright (C) 2012 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.owncloud.android.authenticator;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.network.SslAnalyzer;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.utils.OwnCloudVersion;
+
+import eu.alefzero.webdav.WebdavClient;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.util.Log;
+
+public class ConnectionCheckOperation extends RemoteOperation {
+
+ /** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs. */
+ public static final int TRY_CONNECTION_TIMEOUT = 5000;
+
+ private static final String TAG = ConnectionCheckerRunnable.class.getCanonicalName();
+
+ private String mUrl;
+ private RemoteOperationResult mLatestResult;
+ private Context mContext;
+ private OwnCloudVersion mOCVersion;
+
+ public ConnectionCheckOperation(String url, Context context) {
+ mUrl = url;
+ mContext = context;
+ mOCVersion = null;
+ }
+
+ public OwnCloudVersion getDiscoveredVersion() {
+ return mOCVersion;
+ }
+
+ private boolean tryConnection(WebdavClient wc, String urlSt) {
+ boolean retval = false;
+ GetMethod get = null;
+ try {
+ get = new GetMethod(urlSt);
+ int status = wc.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
+ String response = get.getResponseBodyAsString();
+ if (status == HttpStatus.SC_OK) {
+ JSONObject json = new JSONObject(response);
+ if (!json.getBoolean("installed")) {
+ mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
+ } else {
+ mOCVersion = new OwnCloudVersion(json.getString("version"));
+ if (!mOCVersion.isVersionValid()) {
+ mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.BAD_OC_VERSION);
+
+ } else {
+ retval = true;
+ }
+ }
+
+ } else {
+ mLatestResult = new RemoteOperationResult(false, status);
+ }
+
+ } catch (JSONException e) {
+ mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
+ //Log.e(TAG, "JSON exception while trying connection (instance not configured) ", e);
+
+ } catch (Exception e) {
+ mLatestResult = new RemoteOperationResult(e);
+ //Log.e(TAG, "Unexpected exception while trying connection", e);
+
+ } finally {
+ if (get != null)
+ get.releaseConnection();
+ }
+
+ return retval;
+ }
+
+ private boolean isOnline() {
+ ConnectivityManager cm = (ConnectivityManager) mContext
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ return cm != null && cm.getActiveNetworkInfo() != null
+ && cm.getActiveNetworkInfo().isConnectedOrConnecting();
+ }
+
+ @Override
+ protected RemoteOperationResult run(WebdavClient client) {
+ if (!isOnline()) {
+ return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
+ }
+ if (mUrl.startsWith("http://") || mUrl.startsWith("https://")) {
+ mLatestResult = new RemoteOperationResult(
+ mUrl.startsWith("https://") ? RemoteOperationResult.ResultCode.OK_SSL : RemoteOperationResult.ResultCode.OK_NO_SSL
+ );
+ tryConnection(client, mUrl + AccountUtils.STATUS_PATH);
+ return mLatestResult;
+
+ } else {
+ client.setBaseUri(Uri.parse("https://" + mUrl + AccountUtils.STATUS_PATH));
+ if (tryConnection(client, "https://" + mUrl + AccountUtils.STATUS_PATH)) {
+ return new RemoteOperationResult(RemoteOperationResult.ResultCode.OK_SSL);
+
+ } else if (!SslAnalyzer.isRecoverable(mLatestResult)) {
+
+ Log.d(TAG, "establishing secure connection failed, trying non secure connection");
+ client.setBaseUri(Uri.parse("http://" + mUrl + AccountUtils.STATUS_PATH));
+ if (tryConnection(client, "http://" + mUrl + AccountUtils.STATUS_PATH)) {
+ return new RemoteOperationResult(RemoteOperationResult.ResultCode.OK_NO_SSL);
+ }
+ }
+ return mLatestResult;
+ }
+ }
+
+}
diff --git a/src/com/owncloud/android/authenticator/ConnectionCheckerRunnable.java b/src/com/owncloud/android/authenticator/ConnectionCheckerRunnable.java
index 2d32f188..ec7dbdc9 100644
--- a/src/com/owncloud/android/authenticator/ConnectionCheckerRunnable.java
+++ b/src/com/owncloud/android/authenticator/ConnectionCheckerRunnable.java
@@ -36,7 +36,7 @@ import org.json.JSONObject;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authenticator.OnConnectCheckListener.ResultType;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.utils.OwnCloudVersion;
import eu.alefzero.webdav.WebdavClient;
@@ -107,7 +107,7 @@ public class ConnectionCheckerRunnable implements Runnable {
boolean retval = false;
GetMethod get = null;
try {
- WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(urlSt));
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(urlSt), mContext);
get = new GetMethod(urlSt);
int status = wc.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
String response = get.getResponseBodyAsString();
diff --git a/src/com/owncloud/android/authenticator/EasySSLSocketFactory.java b/src/com/owncloud/android/authenticator/EasySSLSocketFactory.java
deleted file mode 100644
index 1bb1aa6b..00000000
--- a/src/com/owncloud/android/authenticator/EasySSLSocketFactory.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * $HeadURL$
- * $Revision$
- * $Date$
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
- *
- */
-
-package com.owncloud.android.authenticator;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.UnknownHostException;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-import org.apache.commons.httpclient.ConnectTimeoutException;
-import org.apache.commons.httpclient.HttpClientError;
-import org.apache.commons.httpclient.params.HttpConnectionParams;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
-import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
-
-import android.util.Log;
-
-/**
- *
- * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s that
- * accept self-signed certificates.
- *
- *
- * This socket factory SHOULD NOT be used for productive systems due to security
- * reasons, unless it is a concious decision and you are perfectly aware of
- * security implications of accepting self-signed certificates
- *
- *
- *
- * Example of using custom protocol socket factory for a specific host:
- *
- *
- * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(),
- * 443);
- *
- * URI uri = new URI("https://localhost/", true);
- * // use relative url only
- * GetMethod httpget = new GetMethod(uri.getPathQuery());
- * HostConfiguration hc = new HostConfiguration();
- * hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
- * HttpClient client = new HttpClient();
- * client.executeMethod(hc, httpget);
- *
- *
- *
- *
- * Example of using custom protocol socket factory per default instead of the
- * standard one:
- *
- *
- * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(),
- * 443);
- * Protocol.registerProtocol("https", easyhttps);
- *
- * HttpClient client = new HttpClient();
- * GetMethod httpget = new GetMethod("https://localhost/");
- * client.executeMethod(httpget);
- *
- * DISCLAIMER: HttpClient developers DO NOT actively support this
- * component. The component is provided as a reference material, which
- * may be inappropriate for use without additional customization.
- *
- */
-
-public class EasySSLSocketFactory implements ProtocolSocketFactory {
-
- private static final String TAG = "EasySSLSocketFactory";
- private SSLContext sslcontext = null;
-
- /**
- * Constructor for EasySSLProtocolSocketFactory.
- */
- public EasySSLSocketFactory() {
- super();
- }
-
- private static SSLContext createEasySSLContext() {
- Log.d(TAG, "Creating Easy SSL Context");
- try {
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, new TrustManager[] { new EasyX509TrustManager(
- null) }, null);
- return context;
- } catch (Exception er) {
- Log.e(TAG, er.getMessage() + "");
- throw new HttpClientError(er.toString());
- }
- }
-
- private SSLContext getSSLContext() {
- Log.d(TAG, "Getting Easy SSL Context");
- if (this.sslcontext == null) {
- this.sslcontext = createEasySSLContext();
- }
- return this.sslcontext;
- }
-
- /**
- * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
- */
- public Socket createSocket(String host, int port, InetAddress clientHost,
- int clientPort) throws IOException, UnknownHostException {
- Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", client " + clientHost + ":" + clientPort);
-
- return getSSLContext().getSocketFactory().createSocket(host, port,
- clientHost, clientPort);
- }
-
- /**
- * Attempts to get a new socket connection to the given host within the
- * given time limit.
- *
- * To circumvent the limitations of older JREs that do not support connect
- * timeout a controller thread is executed. The controller thread attempts
- * to create a new socket within the given limit of time. If socket
- * constructor does not return until the timeout expires, the controller
- * terminates and throws an {@link ConnectTimeoutException}
- *
- *
- * @param host the host name/IP
- * @param port the port on the host
- * @param clientHost the local host name/IP to bind the socket to
- * @param clientPort the port on the local machine
- * @param params {@link HttpConnectionParams Http connection parameters}
- *
- * @return Socket a new socket
- *
- * @throws IOException if an I/O error occurs while creating the socket
- * @throws UnknownHostException if the IP address of the host cannot be
- * determined
- */
- public Socket createSocket(final String host, final int port,
- final InetAddress localAddress, final int localPort,
- final HttpConnectionParams params) throws IOException,
- UnknownHostException, ConnectTimeoutException {
- Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
- if (params == null) {
- throw new IllegalArgumentException("Parameters may not be null");
- }
- int timeout = params.getConnectionTimeout();
- SocketFactory socketfactory = getSSLContext().getSocketFactory();
- /*if (timeout == 0) {
- Log.d(TAG, " ... with connection timeout 0 and socket timeout " + params.getSoTimeout());
- Socket socket = socketfactory.createSocket(host, port, localAddress,
- localPort);
- socket.setSoTimeout(params.getSoTimeout());
- return socket;
- } else {*/
- Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
- Socket socket = socketfactory.createSocket();
- SocketAddress localaddr = new InetSocketAddress(localAddress,
- localPort);
- SocketAddress remoteaddr = new InetSocketAddress(host, port);
- socket.setSoTimeout(params.getSoTimeout());
- socket.bind(localaddr);
- socket.connect(remoteaddr, timeout);
- return socket;
- //}
- }
-
- /**
- * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
- */
- public Socket createSocket(String host, int port) throws IOException,
- UnknownHostException {
- Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
- return getSSLContext().getSocketFactory().createSocket(host, port);
- }
-
- /**
- * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
- */
- public Socket createSocket(Socket socket, String host, int port,
- boolean autoClose) throws IOException, UnknownHostException {
- Log.d(TAG, "Creating SSL Socket from other shocket " + socket + " to remote " + host + ":" + port);
- return getSSLContext().getSocketFactory().createSocket(socket, host,
- port, autoClose);
- }
-
- public boolean equals(Object obj) {
- return ((obj != null) && obj.getClass().equals(
- EasySSLSocketFactory.class));
- }
-
- public int hashCode() {
- return EasySSLSocketFactory.class.hashCode();
- }
-
-}
\ No newline at end of file
diff --git a/src/com/owncloud/android/authenticator/EasyX509TrustManager.java b/src/com/owncloud/android/authenticator/EasyX509TrustManager.java
deleted file mode 100644
index 0c7b0834..00000000
--- a/src/com/owncloud/android/authenticator/EasyX509TrustManager.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.owncloud.android.authenticator;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * @author olamy
- * @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse
- * $
- * @since 1.2.3
- */
-public class EasyX509TrustManager implements X509TrustManager {
-
- private X509TrustManager standardTrustManager = null;
-
- /**
- * Constructor for EasyX509TrustManager.
- */
- public EasyX509TrustManager(KeyStore keystore)
- throws NoSuchAlgorithmException, KeyStoreException {
- super();
- TrustManagerFactory factory = TrustManagerFactory
- .getInstance(TrustManagerFactory.getDefaultAlgorithm());
- factory.init(keystore);
- TrustManager[] trustmanagers = factory.getTrustManagers();
- if (trustmanagers.length == 0) {
- throw new NoSuchAlgorithmException("no trust manager found");
- }
- this.standardTrustManager = (X509TrustManager) trustmanagers[0];
- }
-
- /**
- * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
- * String authType)
- */
- public void checkClientTrusted(X509Certificate[] certificates,
- String authType) throws CertificateException {
- standardTrustManager.checkClientTrusted(certificates, authType);
- }
-
- /**
- * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
- * String authType)
- */
- public void checkServerTrusted(X509Certificate[] certificates,
- String authType) throws CertificateException {
- if ((certificates != null) && (certificates.length == 1)) {
- certificates[0].checkValidity();
- } else {
- // standardTrustManager.checkServerTrusted( certificates, authType
- // );
- }
- }
-
- /**
- * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
- */
- public X509Certificate[] getAcceptedIssuers() {
- return this.standardTrustManager.getAcceptedIssuers();
- }
-
-}
\ No newline at end of file
diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java
index d88dbb0c..59d5daaa 100644
--- a/src/com/owncloud/android/files/services/FileDownloader.java
+++ b/src/com/owncloud/android/files/services/FileDownloader.java
@@ -8,7 +8,8 @@ import java.util.Map;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import eu.alefzero.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+
+import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
diff --git a/src/com/owncloud/android/files/services/FileOperation.java b/src/com/owncloud/android/files/services/FileOperation.java
index ce61dc77..4215a1fc 100644
--- a/src/com/owncloud/android/files/services/FileOperation.java
+++ b/src/com/owncloud/android/files/services/FileOperation.java
@@ -21,7 +21,7 @@ import java.io.File;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.content.Context;
diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java
index f7340f6b..e66181be 100644
--- a/src/com/owncloud/android/files/services/FileUploader.java
+++ b/src/com/owncloud/android/files/services/FileUploader.java
@@ -10,7 +10,8 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.PhotoTakenBroadcastReceiver;
import eu.alefzero.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+
+import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.app.Notification;
diff --git a/src/com/owncloud/android/files/services/InstantUploadService.java b/src/com/owncloud/android/files/services/InstantUploadService.java
index 87430697..4b8393d8 100644
--- a/src/com/owncloud/android/files/services/InstantUploadService.java
+++ b/src/com/owncloud/android/files/services/InstantUploadService.java
@@ -22,7 +22,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import eu.alefzero.webdav.WebdavClient;
diff --git a/src/com/owncloud/android/network/AdvancedSslSocketFactory.java b/src/com/owncloud/android/network/AdvancedSslSocketFactory.java
new file mode 100644
index 00000000..3c1d68e1
--- /dev/null
+++ b/src/com/owncloud/android/network/AdvancedSslSocketFactory.java
@@ -0,0 +1,168 @@
+/* ownCloud Android client application
+ * Copyright (C) 2012 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.owncloud.android.network;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+
+import android.util.Log;
+
+/**
+ * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with
+ * a custom SSLContext and an optional Hostname Verifier.
+ *
+ * @author David A. Velasco
+ */
+
+public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
+
+ private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
+
+ private SSLContext mSslContext = null;
+ private X509HostnameVerifier mHostnameVerifier;
+
+ /**
+ * Constructor for AdvancedSSLProtocolSocketFactory.
+ */
+ public AdvancedSslSocketFactory(SSLContext sslContext, X509HostnameVerifier hostnameVerifier) {
+ if (sslContext == null)
+ throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
+ mSslContext = sslContext;
+ mHostnameVerifier = hostnameVerifier;
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
+ */
+ public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
+ Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
+ verifyHostname(host, socket);
+ return socket;
+ }
+
+
+ /**
+ * Attempts to get a new socket connection to the given host within the
+ * given time limit.
+ *
+ * @param host the host name/IP
+ * @param port the port on the host
+ * @param clientHost the local host name/IP to bind the socket to
+ * @param clientPort the port on the local machine
+ * @param params {@link HttpConnectionParams Http connection parameters}
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ public Socket createSocket(final String host, final int port,
+ final InetAddress localAddress, final int localPort,
+ final HttpConnectionParams params) throws IOException,
+ UnknownHostException, ConnectTimeoutException {
+ Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
+ if (params == null) {
+ throw new IllegalArgumentException("Parameters may not be null");
+ }
+ int timeout = params.getConnectionTimeout();
+ SocketFactory socketfactory = mSslContext.getSocketFactory();
+ Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
+ Socket socket = socketfactory.createSocket();
+ SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
+ SocketAddress remoteaddr = new InetSocketAddress(host, port);
+ socket.setSoTimeout(params.getSoTimeout());
+ socket.bind(localaddr);
+ socket.connect(remoteaddr, timeout);
+ verifyHostname(host, socket);
+ return socket;
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
+ */
+ public Socket createSocket(String host, int port) throws IOException,
+ UnknownHostException {
+ Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
+ Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
+ verifyHostname(host, socket);
+ return socket;
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
+ */
+ /*public Socket createSocket(Socket socket, String host, int port,
+ boolean autoClose) throws IOException, UnknownHostException {
+ Log.d(TAG, "Creating SSL Socket from other shocket " + socket + " to remote " + host + ":" + port);
+ return getSSLContext().getSocketFactory().createSocket(socket, host,
+ port, autoClose);
+ }*/
+
+ public boolean equals(Object obj) {
+ return ((obj != null) && obj.getClass().equals(
+ AdvancedSslSocketFactory.class));
+ }
+
+ public int hashCode() {
+ return AdvancedSslSocketFactory.class.hashCode();
+ }
+
+
+ public X509HostnameVerifier getHostNameVerifier() {
+ return mHostnameVerifier;
+ }
+
+
+ public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
+ mHostnameVerifier = hostnameVerifier;
+ }
+
+ /**
+ * Verifies the host name with the content of the server certificate using the current host name verifier, if some
+ * @param socket
+ */
+ private void verifyHostname(String host, Socket socket) throws IOException {
+ if (mHostnameVerifier != null) {
+ try {
+ mHostnameVerifier.verify(host, (SSLSocket) socket);
+ } catch (IOException iox) {
+ try {
+ socket.close();
+ } catch (Exception x) {}
+ throw iox;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/owncloud/android/network/AdvancedX509TrustManager.java b/src/com/owncloud/android/network/AdvancedX509TrustManager.java
new file mode 100644
index 00000000..13a16e20
--- /dev/null
+++ b/src/com/owncloud/android/network/AdvancedX509TrustManager.java
@@ -0,0 +1,117 @@
+/* ownCloud Android client application
+ * Copyright (C) 2012 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.owncloud.android.network;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertStoreException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import android.util.Log;
+
+/**
+ * @author David A. Velasco
+ */
+public class AdvancedX509TrustManager implements X509TrustManager {
+
+ private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
+
+ private X509TrustManager mStandardTrustManager = null;
+ private KeyStore mKnownServersKeyStore;
+
+ /**
+ * Constructor for AdvancedX509TrustManager
+ *
+ * @param knownServersCertStore Local certificates store with server certificates explicitly trusted by the user.
+ * @throws CertStoreException When no default X509TrustManager instance was found in the system.
+ */
+ public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
+ throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
+ super();
+ TrustManagerFactory factory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init((KeyStore)null);
+ mStandardTrustManager = findX509TrustManager(factory);
+
+ mKnownServersKeyStore = knownServersKeyStore;
+ }
+
+
+ /**
+ * Locates the first X509TrustManager provided by a given TrustManagerFactory
+ * @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
+ * @return The first X509TrustManager found in factory.
+ * @throws CertStoreException When no X509TrustManager instance was found in factory
+ */
+ private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
+ TrustManager tms[] = factory.getTrustManagers();
+ for (int i = 0; i < tms.length; i++) {
+ if (tms[i] instanceof X509TrustManager) {
+ return (X509TrustManager) tms[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
+ * String authType)
+ */
+ public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+ mStandardTrustManager.checkClientTrusted(certificates, authType);
+ }
+
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
+ * String authType)
+ */
+ public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+ if (!isKnownServer(certificates[0])) {
+ Log.d(TAG, "checkClientTrusted() with standard trust manager...");
+ mStandardTrustManager.checkClientTrusted(certificates, authType);
+ }
+ }
+
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+ */
+ public X509Certificate[] getAcceptedIssuers() {
+ return mStandardTrustManager.getAcceptedIssuers();
+ }
+
+
+ private boolean isKnownServer(X509Certificate cert) {
+ try {
+ return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
+ } catch (KeyStoreException e) {
+ Log.d(TAG, "Fail while checking certificate in the known-servers store");
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/owncloud/android/network/EasySSLSocketFactory.java b/src/com/owncloud/android/network/EasySSLSocketFactory.java
new file mode 100644
index 00000000..dca99a4f
--- /dev/null
+++ b/src/com/owncloud/android/network/EasySSLSocketFactory.java
@@ -0,0 +1,230 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package com.owncloud.android.network;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpClientError;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+
+
+import android.util.Log;
+
+/**
+ *
+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s that
+ * accept self-signed certificates.
+ *
+ *
+ * This socket factory SHOULD NOT be used for productive systems due to security
+ * reasons, unless it is a concious decision and you are perfectly aware of
+ * security implications of accepting self-signed certificates
+ *
+ *
+ *
+ * Example of using custom protocol socket factory for a specific host:
+ *
+ *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(),
+ * 443);
+ *
+ * URI uri = new URI("https://localhost/", true);
+ * // use relative url only
+ * GetMethod httpget = new GetMethod(uri.getPathQuery());
+ * HostConfiguration hc = new HostConfiguration();
+ * hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
+ * HttpClient client = new HttpClient();
+ * client.executeMethod(hc, httpget);
+ *
+ *
+ *
+ *
+ * Example of using custom protocol socket factory per default instead of the
+ * standard one:
+ *
+ *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(),
+ * 443);
+ * Protocol.registerProtocol("https", easyhttps);
+ *
+ * HttpClient client = new HttpClient();
+ * GetMethod httpget = new GetMethod("https://localhost/");
+ * client.executeMethod(httpget);
+ *
+ * DISCLAIMER: HttpClient developers DO NOT actively support this
+ * component. The component is provided as a reference material, which
+ * may be inappropriate for use without additional customization.
+ *
+ */
+
+public class EasySSLSocketFactory implements ProtocolSocketFactory {
+
+ private static final String TAG = "EasySSLSocketFactory";
+ private SSLContext sslcontext = null;
+
+ /**
+ * Constructor for EasySSLProtocolSocketFactory.
+ */
+ public EasySSLSocketFactory() {
+ super();
+ }
+
+ private static SSLContext createEasySSLContext() {
+ Log.d(TAG, "Creating Easy SSL Context");
+ try {
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, new TrustManager[] { new EasyX509TrustManager(
+ null) }, null);
+ return context;
+ } catch (Exception er) {
+ Log.e(TAG, er.getMessage() + "");
+ throw new HttpClientError(er.toString());
+ }
+ }
+
+ private SSLContext getSSLContext() {
+ Log.d(TAG, "Getting Easy SSL Context");
+ if (this.sslcontext == null) {
+ this.sslcontext = createEasySSLContext();
+ }
+ return this.sslcontext;
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
+ */
+ public Socket createSocket(String host, int port, InetAddress clientHost,
+ int clientPort) throws IOException, UnknownHostException {
+ Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", client " + clientHost + ":" + clientPort);
+
+ return getSSLContext().getSocketFactory().createSocket(host, port,
+ clientHost, clientPort);
+ }
+
+ /**
+ * Attempts to get a new socket connection to the given host within the
+ * given time limit.
+ *
+ * To circumvent the limitations of older JREs that do not support connect
+ * timeout a controller thread is executed. The controller thread attempts
+ * to create a new socket within the given limit of time. If socket
+ * constructor does not return until the timeout expires, the controller
+ * terminates and throws an {@link ConnectTimeoutException}
+ *
+ *
+ * @param host the host name/IP
+ * @param port the port on the host
+ * @param clientHost the local host name/IP to bind the socket to
+ * @param clientPort the port on the local machine
+ * @param params {@link HttpConnectionParams Http connection parameters}
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ public Socket createSocket(final String host, final int port,
+ final InetAddress localAddress, final int localPort,
+ final HttpConnectionParams params) throws IOException,
+ UnknownHostException, ConnectTimeoutException {
+ Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
+ if (params == null) {
+ throw new IllegalArgumentException("Parameters may not be null");
+ }
+ int timeout = params.getConnectionTimeout();
+ SocketFactory socketfactory = getSSLContext().getSocketFactory();
+ /*if (timeout == 0) {
+ Log.d(TAG, " ... with connection timeout 0 and socket timeout " + params.getSoTimeout());
+ Socket socket = socketfactory.createSocket(host, port, localAddress,
+ localPort);
+ socket.setSoTimeout(params.getSoTimeout());
+ return socket;
+ } else {*/
+ Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
+ Socket socket = socketfactory.createSocket();
+ SocketAddress localaddr = new InetSocketAddress(localAddress,
+ localPort);
+ SocketAddress remoteaddr = new InetSocketAddress(host, port);
+ socket.setSoTimeout(params.getSoTimeout());
+ socket.bind(localaddr);
+ socket.connect(remoteaddr, timeout);
+ return socket;
+ //}
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
+ */
+ public Socket createSocket(String host, int port) throws IOException,
+ UnknownHostException {
+ Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
+ return getSSLContext().getSocketFactory().createSocket(host, port);
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
+ */
+ public Socket createSocket(Socket socket, String host, int port,
+ boolean autoClose) throws IOException, UnknownHostException {
+ Log.d(TAG, "Creating SSL Socket from other shocket " + socket + " to remote " + host + ":" + port);
+ return getSSLContext().getSocketFactory().createSocket(socket, host,
+ port, autoClose);
+ }
+
+ public boolean equals(Object obj) {
+ return ((obj != null) && obj.getClass().equals(
+ EasySSLSocketFactory.class));
+ }
+
+ public int hashCode() {
+ return EasySSLSocketFactory.class.hashCode();
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/owncloud/android/network/EasyX509TrustManager.java b/src/com/owncloud/android/network/EasyX509TrustManager.java
new file mode 100644
index 00000000..1ac62186
--- /dev/null
+++ b/src/com/owncloud/android/network/EasyX509TrustManager.java
@@ -0,0 +1,88 @@
+package com.owncloud.android.network;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * @author olamy
+ * @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse
+ * $
+ * @since 1.2.3
+ */
+public class EasyX509TrustManager implements X509TrustManager {
+
+ private X509TrustManager standardTrustManager = null;
+
+ /**
+ * Constructor for EasyX509TrustManager.
+ */
+ public EasyX509TrustManager(KeyStore keystore)
+ throws NoSuchAlgorithmException, KeyStoreException {
+ super();
+ TrustManagerFactory factory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init(keystore);
+ TrustManager[] trustmanagers = factory.getTrustManagers();
+ if (trustmanagers.length == 0) {
+ throw new NoSuchAlgorithmException("no trust manager found");
+ }
+ this.standardTrustManager = (X509TrustManager) trustmanagers[0];
+ }
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
+ * String authType)
+ */
+ public void checkClientTrusted(X509Certificate[] certificates,
+ String authType) throws CertificateException {
+ standardTrustManager.checkClientTrusted(certificates, authType);
+ }
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
+ * String authType)
+ */
+ public void checkServerTrusted(X509Certificate[] certificates,
+ String authType) throws CertificateException {
+ if ((certificates != null) && (certificates.length == 1)) {
+ certificates[0].checkValidity();
+ } else {
+ // standardTrustManager.checkServerTrusted( certificates, authType
+ // );
+ }
+ }
+
+ /**
+ * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+ */
+ public X509Certificate[] getAcceptedIssuers() {
+ return this.standardTrustManager.getAcceptedIssuers();
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/owncloud/android/network/OwnCloudClientUtils.java b/src/com/owncloud/android/network/OwnCloudClientUtils.java
new file mode 100644
index 00000000..a76cd4a2
--- /dev/null
+++ b/src/com/owncloud/android/network/OwnCloudClientUtils.java
@@ -0,0 +1,283 @@
+/* ownCloud Android client application
+ * Copyright (C) 2011 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.owncloud.android.network;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.protocol.Protocol;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.utils.OwnCloudVersion;
+
+import eu.alefzero.webdav.WebdavClient;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+public class OwnCloudClientUtils {
+
+ final private static String TAG = "OwnCloudClientFactory";
+
+ /** Default timeout for waiting data from the server */
+ public static final int DEFAULT_DATA_TIMEOUT = 60000;
+
+ /** Default timeout for establishing a connection */
+ public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
+
+ /** Connection manager for all the WebdavClients */
+ private static MultiThreadedHttpConnectionManager mConnManager = null;
+
+ private static Protocol mDefaultHttpsProtocol = null;
+
+ private static AdvancedSslSocketFactory mAdvancedSslSocketFactory = null;
+
+
+ /**
+ * Creates a WebdavClient setup for an ownCloud account
+ *
+ * @param account The ownCloud account
+ * @param context The application context
+ * @return A WebdavClient object ready to be used
+ */
+ public static WebdavClient createOwnCloudClient (Account account, Context context) {
+ Log.d(TAG, "Creating WebdavClient associated to " + account.name);
+
+ String baseUrl = AccountManager.get(context).getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL);
+ OwnCloudVersion ownCloudVersion = new OwnCloudVersion(AccountManager.get(context).getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
+ String webDavPath = AccountUtils.getWebdavPath(ownCloudVersion);
+
+ WebdavClient client = createOwnCloudClient(Uri.parse(baseUrl + webDavPath), context);
+
+ String username = account.name.substring(0, account.name.lastIndexOf('@'));
+ String password = AccountManager.get(context).getPassword(account);
+ //String password = am.blockingGetAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE, true);
+
+ client.setCredentials(username, password);
+
+ return client;
+ }
+
+
+ /**
+ * Creates a WebdavClient to try a new account before saving it
+ *
+ * @param uri URL to the ownCloud server
+ * @param username User name
+ * @param password User password
+ * @param context Android context where the WebdavClient is being created.
+ * @return A WebdavClient object ready to be used
+ */
+ public static WebdavClient createOwnCloudClient(Uri uri, String username, String password, Context context) {
+ Log.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
+
+ WebdavClient client = createOwnCloudClient(uri, context);
+
+ client.setCredentials(username, password);
+
+ return client;
+ }
+
+
+ /**
+ * Creates a WebdavClient to access a URL and sets the desired parameters for ownCloud client connections.
+ *
+ * @param uri URL to the ownCloud server
+ * @param context Android context where the WebdavClient is being created.
+ * @return A WebdavClient object ready to be used
+ */
+ public static WebdavClient createOwnCloudClient(Uri uri, Context context) {
+ Log.d(TAG, "Creating WebdavClient for " + uri);
+
+ //allowSelfsignedCertificates(true);
+ try {
+ registerAdvancedSslContext(true, context);
+ } catch (GeneralSecurityException e) {
+ Log.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
+
+ } catch (IOException e) {
+ Log.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
+ }
+
+ WebdavClient client = new WebdavClient(getMultiThreadedConnManager());
+
+ client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
+ client.setBaseUri(uri);
+
+ return client;
+ }
+
+
+ /**
+ * Allows or disallows self-signed certificates in ownCloud servers to reach
+ *
+ * @param allow 'True' to allow, 'false' to disallow
+ */
+ public static void allowSelfsignedCertificates(boolean allow) {
+ Protocol pr = null;
+ try {
+ pr = Protocol.getProtocol("https");
+ if (pr != null && mDefaultHttpsProtocol == null) {
+ mDefaultHttpsProtocol = pr;
+ }
+ } catch (IllegalStateException e) {
+ // nothing to do here; really
+ }
+ boolean isAllowed = (pr != null && pr.getSocketFactory() instanceof EasySSLSocketFactory);
+ if (allow && !isAllowed) {
+ Protocol.registerProtocol("https", new Protocol("https", new EasySSLSocketFactory(), 443));
+ } else if (!allow && isAllowed) {
+ if (mDefaultHttpsProtocol != null) {
+ Protocol.registerProtocol("https", mDefaultHttpsProtocol);
+ }
+ }
+ }
+
+
+ /**
+ * Registers or unregisters the proper components for advanced SSL handling.
+ * @throws IOException
+ */
+ private static void registerAdvancedSslContext(boolean register, Context context) throws GeneralSecurityException, IOException {
+ Protocol pr = null;
+ try {
+ pr = Protocol.getProtocol("https");
+ if (pr != null && mDefaultHttpsProtocol == null) {
+ mDefaultHttpsProtocol = pr;
+ }
+ } catch (IllegalStateException e) {
+ // nothing to do here; really
+ }
+ boolean isRegistered = (pr != null && pr.getSocketFactory() instanceof AdvancedSslSocketFactory);
+ if (register && !isRegistered) {
+ Protocol.registerProtocol("https", new Protocol("https", getAdvancedSslSocketFactory(context), 443));
+
+ } else if (!register && isRegistered) {
+ if (mDefaultHttpsProtocol != null) {
+ Protocol.registerProtocol("https", mDefaultHttpsProtocol);
+ }
+ }
+ }
+
+ private static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
+ if (mAdvancedSslSocketFactory == null) {
+ KeyStore trustStore = getKnownServersStore(context);
+ AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
+ TrustManager[] tms = new TrustManager[] { trustMgr };
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, tms, null);
+
+ /*} catch (KeyStoreException e) {
+ e.printStackTrace();
+
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+
+ }*/
+ mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, null); // TODO HOST NAME VERIFIER
+ }
+ return mAdvancedSslSocketFactory;
+ }
+
+
+ private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
+
+ private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
+
+ private static KeyStore mKnownServersStore = null;
+
+ /**
+ * Returns the local store of reliable server certificates, explicitly accepted by the user.
+ *
+ * Returns a KeyStore instance with empty content if the local store was never created.
+ *
+ * Loads the store from the storage environment if needed.
+ *
+ * @param context Android context where the operation is being performed.
+ * @return KeyStore instance with explicitly-accepted server certificates.
+ * @throws KeyStoreException When the KeyStore instance could not be created.
+ * @throws IOException When an existing local trust store could not be loaded.
+ * @throws NoSuchAlgorithmException When the existing local trust store was saved with an unsupported algorithm.
+ * @throws CertificateException When an exception occurred while loading the certificates from the local trust store.
+ */
+ private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+ if (mKnownServersStore == null) {
+ //mKnownServersStore = KeyStore.getInstance("BKS");
+ mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
+ Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
+ if (localTrustStoreFile.exists()) {
+ InputStream in = new FileInputStream(localTrustStoreFile);
+ try {
+ mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
+ } finally {
+ in.close();
+ }
+ } else {
+ mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
+ }
+ }
+ return mKnownServersStore;
+ }
+
+
+ public static void addCertToKnownServersStore(Certificate cert, Context context) throws KeyStoreException, NoSuchAlgorithmException,
+ CertificateException, IOException {
+ KeyStore knownServers = getKnownServersStore(context);
+ knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
+ FileOutputStream fos = null;
+ try {
+ fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
+ knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
+ } finally {
+ fos.close();
+ }
+ }
+
+
+ static private MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
+ if (mConnManager == null) {
+ mConnManager = new MultiThreadedHttpConnectionManager();
+ mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
+ mConnManager.getParams().setMaxTotalConnections(5);
+ }
+ return mConnManager;
+ }
+
+}
diff --git a/src/com/owncloud/android/network/SslAnalyzer.java b/src/com/owncloud/android/network/SslAnalyzer.java
new file mode 100644
index 00000000..2f02c4b6
--- /dev/null
+++ b/src/com/owncloud/android/network/SslAnalyzer.java
@@ -0,0 +1,82 @@
+/* ownCloud Android client application
+ * Copyright (C) 2011 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.owncloud.android.network;
+
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import com.owncloud.android.operations.RemoteOperationResult;
+
+/**
+ * Helper class to check if a SSL error is related to a condition that could be avoided with assistance from the user.
+ *
+ * @author David A. Velasco
+ */
+public class SslAnalyzer {
+
+ /**
+ * Search for a SSL-related exception in a remote operation result that can be recoverable
+ * by allowing the user to state the reliability of the certificate from the server.
+ *
+ * @param result Result of a remote operation.
+ * @return An exception instance that caused the failure of the remote operation and that can be avoided if the user
+ * states the certificate from the server as reliable; or NULL if the result is that's not possible
+ */
+ public static Exception getRecoverableException(RemoteOperationResult result) {
+ Exception ret = null;
+ SSLException e = (SSLException)result.getException();
+ Throwable cause = null;
+ if (e != null) {
+ if (e instanceof SSLPeerUnverifiedException) {
+ ret = e;
+
+ } else {
+ cause = e.getCause();
+ Throwable previousCause = null;
+ boolean recoverableCertException = false;
+ while (cause != null && cause != previousCause && !recoverableCertException) { // getCause() is not funny
+ recoverableCertException = ( cause instanceof CertPathValidatorException ||
+ cause instanceof CertificateExpiredException ||
+ cause instanceof CertificateNotYetValidException );
+ if (recoverableCertException)
+ ret = (Exception)cause;
+ previousCause = cause;
+ cause = cause.getCause();
+ }
+ }
+ }
+ return ret;
+ }
+
+
+ /**
+ * Checks if a remote operation result can be recoverable
+ * by allowing the user to state the reliability of the certificate from the server.
+ *
+ * @param result Result of a remote operation.
+ * @return An exception instance that caused the failure of the remote operation and that can be avoided if the user
+ * states the certificate from the server as reliable; or NULL if the result is that's not possible
+ */
+ public static boolean isRecoverable(RemoteOperationResult result) {
+ return (getRecoverableException(result) != null);
+ }
+
+}
diff --git a/src/com/owncloud/android/operations/OnRemoteOperationListener.java b/src/com/owncloud/android/operations/OnRemoteOperationListener.java
new file mode 100644
index 00000000..26537fd8
--- /dev/null
+++ b/src/com/owncloud/android/operations/OnRemoteOperationListener.java
@@ -0,0 +1,7 @@
+package com.owncloud.android.operations;
+
+public interface OnRemoteOperationListener {
+
+ void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
+
+}
diff --git a/src/com/owncloud/android/operations/RemoteOperation.java b/src/com/owncloud/android/operations/RemoteOperation.java
new file mode 100644
index 00000000..5b58e0ca
--- /dev/null
+++ b/src/com/owncloud/android/operations/RemoteOperation.java
@@ -0,0 +1,135 @@
+/* ownCloud Android client application
+ * Copyright (C) 2011 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.owncloud.android.operations;
+
+import android.os.Handler;
+
+import eu.alefzero.webdav.WebdavClient;
+
+/**
+ * Operation which execution involves one or several interactions with an ownCloud server.
+ *
+ * Provides methods to execute the operation both synchronously or asynchronously.
+ *
+ * @author David A. Velasco
+ */
+public abstract class RemoteOperation implements Runnable {
+
+ /** Object to interact with the ownCloud server */
+ private WebdavClient mClient = null;
+
+ /** Callback object to notify about the execution of the remote operation */
+ private OnRemoteOperationListener mListener = null;
+
+ /** Handler to the thread where mListener methods will be called */
+ private Handler mListenerHandler = null;
+
+
+ /**
+ * Abstract method to implement the operation in derived classes.
+ */
+ protected abstract RemoteOperationResult run(WebdavClient client);
+
+
+ /**
+ * Synchronously executes the remote operation
+ *
+ * @param client Client object to reach an ownCloud server during the execution of the operation.
+ * @return Result of the operation.
+ */
+ public final RemoteOperationResult execute(WebdavClient client) {
+ if (client == null)
+ throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
+ mClient = client;
+ return run(client);
+ }
+
+
+ /**
+ * Asynchronously executes the remote operation
+ *
+ * @param client Client object to reach an ownCloud server during the execution of the operation.
+ * @param listener Listener to be notified about the execution of the operation.
+ * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
+ * @return Thread were the remote operation is executed.
+ */
+ public final Thread execute(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
+ if (client == null) {
+ throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
+ }
+ mClient = client;
+
+ if (listener == null) {
+ throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
+ }
+ mListener = listener;
+
+ if (listenerHandler == null) {
+ throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
+ }
+ mListenerHandler = listenerHandler;
+
+ Thread runnerThread = new Thread(this);
+ runnerThread.start();
+ return runnerThread;
+ }
+
+ /**
+ * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
+ *
+ * @param listener Listener to be notified about the execution of the operation.
+ * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
+ * @return Thread were the remote operation is executed.
+ */
+ public final RemoteOperationResult retry() {
+ return execute(mClient);
+ }
+
+ /**
+ * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
+ *
+ * @param listener Listener to be notified about the execution of the operation.
+ * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
+ * @return Thread were the remote operation is executed.
+ */
+ public final Thread retry(OnRemoteOperationListener listener, Handler listenerHandler) {
+ return execute(mClient, listener, listenerHandler);
+ }
+
+
+ /**
+ * Asynchronous execution of the operation
+ * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)},
+ * and result posting.
+ */
+ @Override
+ public final void run() {
+ final RemoteOperationResult result = execute(mClient);
+
+ if (mListenerHandler != null && mListener != null) {
+ mListenerHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mListener.onRemoteOperationFinish(RemoteOperation.this, result);
+ }
+ });
+ }
+ }
+
+
+}
diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java
new file mode 100644
index 00000000..1803f4cf
--- /dev/null
+++ b/src/com/owncloud/android/operations/RemoteOperationResult.java
@@ -0,0 +1,121 @@
+package com.owncloud.android.operations;
+
+import java.net.MalformedURLException;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import javax.net.ssl.SSLException;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpStatus;
+
+
+public class RemoteOperationResult {
+
+ public enum ResultCode { // TODO leave alone our own errors
+ OK,
+ OK_SSL,
+ OK_NO_SSL,
+ UNHANDLED_HTTP_CODE,
+ FILE_NOT_FOUND,
+ INSTANCE_NOT_CONFIGURED,
+ UNKNOWN_ERROR,
+ WRONG_CONNECTION,
+ TIMEOUT,
+ INCORRECT_ADDRESS,
+ HOST_NOT_AVAILABLE,
+ NO_NETWORK_CONNECTION,
+ SSL_ERROR,
+ BAD_OC_VERSION,
+ }
+
+ private boolean mSuccess = false;
+ private int mHttpCode = -1;
+ private Exception mException = null;
+ private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
+
+ public RemoteOperationResult(ResultCode code) {
+ mCode = code;
+ mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
+ }
+
+ public RemoteOperationResult(boolean success, int httpCode) {
+ mSuccess = success;
+ mHttpCode = httpCode;
+
+ if (success) {
+ mCode = ResultCode.OK;
+
+ } else if (httpCode > 0) {
+ switch (httpCode) {
+ case HttpStatus.SC_NOT_FOUND:
+ mCode = ResultCode.FILE_NOT_FOUND;
+ break;
+ case HttpStatus.SC_INTERNAL_SERVER_ERROR:
+ mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
+ break;
+ default:
+ mCode = ResultCode.UNHANDLED_HTTP_CODE;
+ }
+ }
+ }
+
+ public RemoteOperationResult(Exception e) {
+ mException = e;
+
+ if (e instanceof SocketException) {
+ mCode = ResultCode.WRONG_CONNECTION;
+ //Log.e(TAG, "Socket exception while trying connection", e);
+
+ } else if (e instanceof SocketTimeoutException) {
+ mCode = ResultCode.TIMEOUT;
+ //Log.e(TAG, "Socket timeout exception while trying connection", e);
+
+ } else if (e instanceof ConnectTimeoutException) {
+ mCode = ResultCode.TIMEOUT;
+ //Log.e(TAG, "Socket timeout exception while trying connection", e);
+
+ } else if (e instanceof MalformedURLException) {
+ mCode = ResultCode.INCORRECT_ADDRESS;
+ //Log.e(TAG, "Connect exception while trying connection", e);
+
+ } else if (e instanceof UnknownHostException) {
+ mCode = ResultCode.HOST_NOT_AVAILABLE;
+ //Log.e(TAG, "Unknown host exception while trying connection", e);
+
+ } else if (e instanceof SSLException) {
+ mCode = ResultCode.SSL_ERROR;
+ //Log.e(TAG, "SSL exception while trying connection", e);
+
+ } else {
+ mCode = ResultCode.UNKNOWN_ERROR;
+ }
+
+ /* } catch (HttpException e) { // other specific exceptions from org.apache.commons.httpclient
+ Log.e(TAG, "HTTP exception while trying connection", e);
+ } catch (IOException e) { // UnkownsServiceException, and any other transport exceptions that could occur
+ Log.e(TAG, "I/O exception while trying connection", e);
+ } catch (Exception e) {
+ Log.e(TAG, "Unexpected exception while trying connection", e);
+ */
+ }
+
+
+ public boolean isSuccess() {
+ return mSuccess;
+ }
+
+ public int getHttpCode() {
+ return mHttpCode;
+ }
+
+ public ResultCode getCode() {
+ return mCode;
+ }
+
+ public Exception getException() {
+ return mException;
+ }
+
+}
diff --git a/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java b/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
index db5a084d..8cb62343 100644
--- a/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
+++ b/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
@@ -30,7 +30,7 @@ import org.apache.http.protocol.HttpContext;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.datamodel.DataStorageManager;
-import com.owncloud.android.utils.OwnCloudClientUtils;
+import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
diff --git a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
index 4f4cb96a..86d9c4b6 100644
--- a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
+++ b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
@@ -20,21 +20,24 @@ package com.owncloud.android.ui.activity;
import java.net.MalformedURLException;
import java.net.URL;
-import java.net.URLEncoder;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authenticator.AuthenticationRunnable;
-import com.owncloud.android.authenticator.ConnectionCheckerRunnable;
+import com.owncloud.android.authenticator.ConnectionCheckOperation;
import com.owncloud.android.authenticator.OnAuthenticationResultListener;
import com.owncloud.android.authenticator.OnConnectCheckListener;
-import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
-import com.owncloud.android.extensions.ExtensionsAvailableActivity;
-import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.ui.dialog.SslValidatorDialog;
+import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.OnRemoteOperationListener;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
+import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
@@ -55,6 +58,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.owncloud.android.R;
+import eu.alefzero.webdav.WebdavClient;
+
/**
* This Activity is used to add an ownCloud account to the App
*
@@ -62,24 +67,29 @@ import com.owncloud.android.R;
*
*/
public class AuthenticatorActivity extends AccountAuthenticatorActivity
- implements OnAuthenticationResultListener, OnConnectCheckListener,
+ implements OnAuthenticationResultListener, OnConnectCheckListener, OnRemoteOperationListener, OnSslValidatorListener,
OnFocusChangeListener, OnClickListener {
+
private static final int DIALOG_LOGIN_PROGRESS = 0;
+ private static final int DIALOG_SSL_VALIDATOR = 1;
+ private static final int DIALOG_CERT_NOT_SAVED = 2;
private static final String TAG = "AuthActivity";
private Thread mAuthThread;
private AuthenticationRunnable mAuthRunnable;
- private ConnectionCheckerRunnable mConnChkRunnable;
+ //private ConnectionCheckerRunnable mConnChkRunnable = null;
+ private ConnectionCheckOperation mConnChkRunnable;
private final Handler mHandler = new Handler();
private String mBaseUrl;
-
+
private static final String STATUS_TEXT = "STATUS_TEXT";
private static final String STATUS_ICON = "STATUS_ICON";
private static final String STATUS_CORRECT = "STATUS_CORRECT";
private static final String IS_SSL_CONN = "IS_SSL_CONN";
private int mStatusText, mStatusIcon;
private boolean mStatusCorrect, mIsSslConn;
+ private RemoteOperationResult mLastSslFailedResult;
public static final String PARAM_USERNAME = "param_Username";
public static final String PARAM_HOSTNAME = "param_Hostname";
@@ -149,12 +159,47 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
dialog = working_dialog;
break;
}
+ case DIALOG_SSL_VALIDATOR: {
+ SslValidatorDialog sslValidator = SslValidatorDialog.newInstance(this, mLastSslFailedResult, this);
+ if (sslValidator != null)
+ dialog = sslValidator;
+ // else, mLastSslFailedResult is not an SSL fail recoverable by accepting the server certificate as reliable; dialog will still be null
+ break;
+ }
+ case DIALOG_CERT_NOT_SAVED: {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
+ builder.setCancelable(false);
+ builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ };
+ });
+ dialog = builder.create();
+ break;
+ }
default:
Log.e(TAG, "Incorrect dialog called with id = " + id);
}
return dialog;
}
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+ switch (id) {
+ case DIALOG_LOGIN_PROGRESS:
+ case DIALOG_CERT_NOT_SAVED:
+ break;
+ case DIALOG_SSL_VALIDATOR: {
+ ((SslValidatorDialog)dialog).updateResult(mLastSslFailedResult);
+ break;
+ }
+ default:
+ Log.e(TAG, "Incorrect dialog called with id = " + id);
+ }
+ }
+
public void onAuthenticationResult(boolean success, String message) {
if (success) {
TextView username_text = (TextView) findViewById(R.id.account_username), password_text = (TextView) findViewById(R.id.account_password);
@@ -203,6 +248,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
accManager.setUserData(account,
AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable
.getDiscoveredVersion().toString());
+
accManager.setUserData(account,
AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);
@@ -272,6 +318,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
URL uri = null;
String webdav_path = AccountUtils.getWebdavPath(mConnChkRunnable
.getDiscoveredVersion());
+
if (webdav_path == null) {
onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));
return;
@@ -288,7 +335,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
showDialog(DIALOG_LOGIN_PROGRESS);
- mAuthRunnable = new AuthenticationRunnable(uri, username, password);
+ mAuthRunnable = new AuthenticationRunnable(uri, username, password, this);
mAuthRunnable.setOnAuthenticationResultListener(this, mHandler);
mAuthThread = new Thread(mAuthRunnable);
mAuthThread.start();
@@ -383,10 +430,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (uri.length() != 0) {
setResultIconAndText(R.drawable.progress_small,
R.string.auth_testing_connection);
- mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);
- mConnChkRunnable.setListener(this, mHandler);
- mAuthThread = new Thread(mConnChkRunnable);
- mAuthThread.start();
+ //mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);
+ mConnChkRunnable = new ConnectionCheckOperation(uri, this);
+ //mConnChkRunnable.setListener(this, mHandler);
+ //mAuthThread = new Thread(mConnChkRunnable);
+ //mAuthThread.start();
+ WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);
+ mAuthThread = mConnChkRunnable.execute(client, this, mHandler);
} else {
findViewById(R.id.refreshButton).setVisibility(
View.INVISIBLE);
@@ -436,4 +486,108 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
view.setInputType(input_type);
}
}
+
+ @Override
+ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+ if (operation.equals(mConnChkRunnable)) {
+
+ mStatusText = mStatusIcon = 0;
+ mStatusCorrect = false;
+ String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
+ .toString().trim().toLowerCase();
+
+ switch (result.getCode()) {
+ case OK_SSL:
+ mIsSslConn = true;
+ mStatusIcon = android.R.drawable.ic_secure;
+ mStatusText = R.string.auth_secure_connection;
+ mStatusCorrect = true;
+ break;
+
+ case OK_NO_SSL:
+ case OK:
+ mIsSslConn = false;
+ mStatusCorrect = true;
+ if (t_url.startsWith("http://") ) {
+ mStatusText = R.string.auth_connection_established;
+ mStatusIcon = R.drawable.ic_ok;
+ } else {
+ mStatusText = R.string.auth_nossl_plain_ok_title;
+ mStatusIcon = android.R.drawable.ic_partial_secure;
+ }
+ break;
+
+
+ case BAD_OC_VERSION:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_bad_oc_version_title;
+ break;
+ case WRONG_CONNECTION:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_wrong_connection_title;
+ break;
+ case TIMEOUT:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_timeout_title;
+ break;
+ case INCORRECT_ADDRESS:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_incorrect_address_title;
+ break;
+
+ case SSL_ERROR:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_ssl_general_error_title;
+ //mStatusText = R.string.auth_ssl_unverified_server_title;
+ mLastSslFailedResult = result;
+ showDialog(DIALOG_SSL_VALIDATOR); // see onCreateDialog(); it does not always show the dialog
+ /*if (InteractiveSslValidatorActivity.isRecoverable(result)) {
+ Intent intent = new Intent(this, InteractiveSslValidatorActivity.class);
+ startActivityForResult(intent, REQUEST_FOR_SSL_CERT);
+ }*/
+ break;
+
+ case HOST_NOT_AVAILABLE:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_unknown_host_title;
+ break;
+ case NO_NETWORK_CONNECTION:
+ mStatusIcon = R.drawable.no_network;
+ mStatusText = R.string.auth_no_net_conn_title;
+ break;
+ case INSTANCE_NOT_CONFIGURED:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_not_configured_title;
+ break;
+ case FILE_NOT_FOUND:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_incorrect_path_title;
+ break;
+ case UNHANDLED_HTTP_CODE:
+ case UNKNOWN_ERROR:
+ mStatusIcon = R.drawable.common_error;
+ mStatusText = R.string.auth_unknown_error_title;
+ break;
+ default:
+ Log.e(TAG, "Incorrect connection checker result type: " + operation);
+ }
+ setResultIconAndText(mStatusIcon, mStatusText);
+ if (!mStatusCorrect)
+ findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
+ else
+ findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
+ findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
+ }
+ }
+
+
+ public void onSavedCertificate() {
+ mAuthThread = mConnChkRunnable.retry(this, mHandler);
+ }
+
+ @Override
+ public void onFailedSavingCertificate() {
+ showDialog(DIALOG_CERT_NOT_SAVED);
+ }
+
}
diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java
index ff763167..0d3acffd 100644
--- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java
+++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java
@@ -71,10 +71,10 @@ import com.owncloud.android.files.OwnCloudFileObserver;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.syncadapter.FileSyncService;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.fragment.OCFileListFragment;
-import com.owncloud.android.utils.OwnCloudClientUtils;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
diff --git a/src/com/owncloud/android/ui/dialog/SslValidatorDialog.java b/src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
new file mode 100644
index 00000000..87e33f7b
--- /dev/null
+++ b/src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
@@ -0,0 +1,193 @@
+/* ownCloud Android client application
+ * Copyright (C) 2011 Bartek Przybylski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.owncloud.android.ui.dialog;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.network.SslAnalyzer;
+import com.owncloud.android.operations.RemoteOperationResult;
+
+/**
+ * Dialog to request the user about a certificate that could not be validated with the certificates store in the system.
+ *
+ * @author David A. Velasco
+ */
+public class SslValidatorDialog extends Dialog {
+
+ private final static String TAG = SslValidatorDialog.class.getSimpleName();
+
+ private OnSslValidatorListener mListener;
+ private Exception mException = null;
+ private View mView;
+
+
+ /**
+ * Creates a new SslValidatorDialog to ask the user if an untrusted certificate from a server should
+ * be trusted.
+ *
+ * @param context Android context where the dialog will live.
+ * @param result Result of a failed remote operation.
+ * @param listener Object to notice when the server certificate was added to the local certificates store.
+ * @return A new SslValidatorDialog instance, or NULL if the operation can not be recovered
+ * by setting the certificate as reliable.
+ */
+ public static SslValidatorDialog newInstance(Context context, RemoteOperationResult result, OnSslValidatorListener listener) {
+ Exception e = SslAnalyzer.getRecoverableException(result);
+ if (e != null) {
+ SslValidatorDialog dialog = new SslValidatorDialog(context, listener);
+ return dialog;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Private constructor.
+ *
+ * Instances have to be created through static {@link SslValidatorDialog#newInstance}.
+ *
+ * @param context Android context where the dialog will live
+ * @param e Exception causing the need of prompt the user about the server certificate.
+ * @param listener Object to notice when the server certificate was added to the local certificates store.
+ */
+ private SslValidatorDialog(Context context, OnSslValidatorListener listener) {
+ super(context);
+ mListener = listener;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mView = getLayoutInflater().inflate(R.layout.ssl_validator_layout, null);
+ setContentView(mView);
+ //setTitle(R.string.ssl_validator_title);
+
+ mView.findViewById(R.id.ok).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ try {
+ saveServerCert();
+ dismiss();
+ if (mListener != null)
+ mListener.onSavedCertificate();
+ else
+ Log.d(TAG, "Nobody there to notify the certificate was saved");
+
+ } catch (Exception e) {
+ dismiss();
+ if (mListener != null)
+ mListener.onFailedSavingCertificate();
+ Log.e(TAG, "Server certificate could not be saved in the known servers trust store ", e);
+ }
+ }
+ });
+
+ mView.findViewById(R.id.cancel).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ cancel();
+ }
+ });
+ }
+
+
+ public void updateResult(RemoteOperationResult result) {
+ mException = SslAnalyzer.getRecoverableException(result);
+ if (mException instanceof CertPathValidatorException ) {
+ showCertificateData(((CertPathValidatorException)mException).getCertPath());
+ ((TextView)mView.findViewById(R.id.reason_cert_not_trusted)).setVisibility(View.VISIBLE);
+ ((TextView)mView.findViewById(R.id.reason_cert_expired)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_not_yet_valid)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_hostname_not_vertified)).setVisibility(View.GONE);
+
+ } else if (mException instanceof CertificateExpiredException ) {
+ ((TextView)mView.findViewById(R.id.reason_cert_not_trusted)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_expired)).setVisibility(View.VISIBLE);
+ ((TextView)mView.findViewById(R.id.reason_cert_not_yet_valid)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_hostname_not_vertified)).setVisibility(View.GONE);
+
+ } else if (mException instanceof CertificateNotYetValidException ) {
+ ((TextView)mView.findViewById(R.id.reason_cert_not_trusted)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_expired)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_not_yet_valid)).setVisibility(View.VISIBLE);
+ ((TextView)mView.findViewById(R.id.reason_hostname_not_vertified)).setVisibility(View.GONE);
+
+ } else if (mException instanceof SSLPeerUnverifiedException ) {
+ ((TextView)mView.findViewById(R.id.reason_cert_not_trusted)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_expired)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_cert_not_yet_valid)).setVisibility(View.GONE);
+ ((TextView)mView.findViewById(R.id.reason_hostname_not_vertified)).setVisibility(View.VISIBLE);
+ }
+
+ }
+
+ private void showCertificateData(CertPath certPath) {
+ final List extends Certificate> certs = certPath.getCertificates();
+ /*X509Certificate badCert = null;
+ if (e.getIndex() >= 0 && e.getIndex() < certs.size())
+ badCert = (X509Certificate) certs.get(e.getIndex());*/
+ if (certs.size() > 0) {
+ X509Certificate serverCert = (X509Certificate) certs.get(0);
+ String text = serverCert.getSubjectDN().getName();
+ text = text.substring(text.indexOf(",") + 1);
+ ((TextView)mView.findViewById(R.id.issuer)).setText(text);
+ }
+ }
+
+ private void saveServerCert() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
+ // TODO be able to add certificate for any recoverable exception
+ if (mException instanceof CertPathValidatorException) {
+ OwnCloudClientUtils.addCertToKnownServersStore(((CertPathValidatorException) mException).getCertPath().getCertificates().get(0), getContext());
+ }
+ }
+
+
+ public interface OnSslValidatorListener {
+ public void onSavedCertificate();
+ public void onFailedSavingCertificate();
+ }
+}
+
diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java
index 5c9b122d..d251883a 100644
--- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java
+++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java
@@ -81,9 +81,9 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.utils.OwnCloudClientUtils;
import com.owncloud.android.utils.OwnCloudVersion;
import com.owncloud.android.R;
diff --git a/src/com/owncloud/android/utils/OwnCloudClientUtils.java b/src/com/owncloud/android/utils/OwnCloudClientUtils.java
deleted file mode 100644
index 9f5ecf52..00000000
--- a/src/com/owncloud/android/utils/OwnCloudClientUtils.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/* ownCloud Android client application
- * Copyright (C) 2011 Bartek Przybylski
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-package com.owncloud.android.utils;
-
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.protocol.Protocol;
-
-import com.owncloud.android.AccountUtils;
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.authenticator.EasySSLSocketFactory;
-import com.owncloud.android.utils.OwnCloudVersion;
-
-import eu.alefzero.webdav.WebdavClient;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.Context;
-import android.net.Uri;
-import android.util.Log;
-
-public class OwnCloudClientUtils {
-
- final private static String TAG = "OwnCloudClientFactory";
-
- /** Default timeout for waiting data from the server */
- public static final int DEFAULT_DATA_TIMEOUT = 60000;
-
- /** Default timeout for establishing a connection */
- public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
-
- /** Connection manager for all the WebdavClients */
- static private MultiThreadedHttpConnectionManager mConnManager = null;
-
-
- /**
- * Creates a WebdavClient setup for an ownCloud account
- *
- * @param account The ownCloud account
- * @param context The application context
- * @return A WebdavClient object ready to be used
- */
- public static WebdavClient createOwnCloudClient (Account account, Context context) {
- Log.d(TAG, "Creating WebdavClient associated to " + account.name);
-
- String baseUrl = AccountManager.get(context).getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL);
- OwnCloudVersion ownCloudVersion = new OwnCloudVersion(AccountManager.get(context).getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
- String webDavPath = AccountUtils.getWebdavPath(ownCloudVersion);
-
- WebdavClient client = createOwnCloudClient(Uri.parse(baseUrl + webDavPath));
-
- String username = account.name.substring(0, account.name.lastIndexOf('@'));
- String password = AccountManager.get(context).getPassword(account);
- //String password = am.blockingGetAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE, true);
-
- client.setCredentials(username, password);
-
- return client;
- }
-
-
- /**
- * Creates a WebdavClient to try a new account before saving it
- *
- * @param uri URL to the ownCloud server
- * @param username User name
- * @param password User password
- * @return A WebdavClient object ready to be used
- */
- public static WebdavClient createOwnCloudClient(Uri uri, String username, String password) {
- Log.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
-
- WebdavClient client = createOwnCloudClient(uri);
-
- client.setCredentials(username, password);
-
- return client;
- }
-
-
- /**
- * Creates a WebdavClient to access a URL and sets the desired parameters for ownCloud client connections.
- *
- * @param uri URL to the ownCloud server
- * @return A WebdavClient object ready to be used
- */
- public static WebdavClient createOwnCloudClient(Uri uri) {
- Log.d(TAG, "Creating WebdavClient for " + uri);
-
- allowSelfsignedCertificates(true);
-
- WebdavClient client = new WebdavClient(getMultiThreadedConnManager());
-
- allowSelfsignedCertificates(true);
- client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
- client.setBaseUri(uri);
-
- return client;
- }
-
-
- /**
- * Allows or disallows self-signed certificates in ownCloud servers to reach
- *
- * @param allow 'True' to allow, 'false' to disallow
- */
- public static void allowSelfsignedCertificates(boolean allow) {
- Protocol pr = null;
- try {
- pr = Protocol.getProtocol("https");
- } catch (IllegalStateException e) {
- // nothing to do here; really
- }
- boolean isAllowed = (pr != null && pr.getSocketFactory() instanceof EasySSLSocketFactory);
- if (allow && !isAllowed) {
- Protocol.registerProtocol("https", new Protocol("https", new EasySSLSocketFactory(), 443));
- } else if (!allow && isAllowed) {
- // TODO - a more strict SocketFactory object should be provided here
- }
- }
-
-
-
- static private MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
- if (mConnManager == null) {
- mConnManager = new MultiThreadedHttpConnectionManager();
- mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
- mConnManager.getParams().setMaxTotalConnections(5);
- }
- return mConnManager;
- }
-
-}