diff --git a/.gitignore b/.gitignore
index 81972b839916a41416ea923cd9c8ed5fab76ace4..b5067c6039560d87fa0bfef02c8a967980113531 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,3 +81,4 @@ G*
 *.dot
 /ics-openvpn/
 /TAGS
+/ics-openvpn
diff --git a/CHANGELOG b/CHANGELOG
index 460d1971ee3eb0aacf2f3ae48cba5b04a4a473c3..35ad29187fd58a6eb4147cfc120bb02863105e8f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,21 @@
+0.5.4 July 21 2014 - the "meetup" release
+Features
+- Renewal of the certificate soon enough
+- After signing up, eip restarts to use the new certificate
+- EIP profiles are named according to their locations
+- Developers: tests run, and network tests are more intensive
+
+0.5.3 June 27 2014- the "beautiful oak" release
+Features
+- Updated ics-openvpn (again).
+- Support for riseup leap provider
+- Always use latests certificate
+Bugs Fixed
+- UI inconsistencies (notification, messages)
+- About text contains correct tracker
+- Long provider names are shown correctly
+- Fewer glue code for ics-openvpn customizations
+
 0.5.2 June 13 2014 - the "new beginning" release
 Features
 - Updated ics-openvpn codebase!
diff --git a/README.md b/README.md
index 68cc075aec6c16f80e522e4b85d43b351d8bbcb0..37ef3bde78ceeaf563c9b748ffc66f4189e0eb08 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,21 @@ The resulting apk(s) will be in `app/build/apk`.
 
 * `Import project` => select bitmask_android top folder
 
+## Running tests
+
+To run the automated tests:
+   1. Run an emulator
+   2. Unlock Android
+   3. Issue the command ./gradlew connectedCheck
+   4. Pay attention and check the "Trust this app" checkbox, if you don't do so tests won't run.
+
+Due to the nature of some tests, adb will lose its connectivity and you won't receive any tests results. To look for failed tests, do the following:
+   1. adb kill-server
+   2. adb logcat | less
+   3. Look for: "failed: test"
+
+We'll polish this process soon, but right now that's what we're doing (well, in fact, we run "adb logcat" in Emacs and then search "failed: test" in the corresponding buffer ;) ).
+
 ## Acknowledgements
 
 This project bases its work in [ics-openvpn project](https://code.google.com/p/ics-openvpn/).
diff --git a/app/build.gradle b/app/build.gradle
index 8c60eb0fa6ace713397adcb21dce9e90f42a9561..c4fdc44b07885fc6efe52d1f2b8b3830c89e5cbc 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,13 +2,12 @@ apply plugin: 'android'
 
 android {
   compileSdkVersion 19
-  buildToolsVersion "19.1.0"
+  buildToolsVersion "20"
 
   defaultConfig {
     minSdkVersion 14
     targetSdkVersion 19
 
-    testPackageName "se.leap.bitmaskclient.test"
     testInstrumentationRunner "android.test.InstrumentationTestRunner"
   }
 
@@ -47,8 +46,9 @@ android {
 }
 
 dependencies {
-  androidTestCompile 'com.android.support:support-v4:+'
-  androidTestCompile 'com.jayway.android.robotium:robotium-solo:4.3.1'
+  // androidTestCompile 'com.android.support:support-v4:20+'
+  // androidTestCompile 'com.android.support:appcompat-v7:20.+'
+  androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.2.1'
   compile 'com.intellij:annotations:12.0'
 }
 
@@ -144,4 +144,4 @@ task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') {
 
   delete ics_openvpn_untranslatable
 }
-build.dependsOn ':app:mergeUntranslatable'
\ No newline at end of file
+//build.dependsOn ':app:mergeUntranslatable'
\ No newline at end of file
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java
index 8ddfbc57743d41ed325df6c2887321ddb1750487..229c345259bfd6b5763c32c5b9eb737a508864e0 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java
@@ -2,7 +2,7 @@ package se.leap.bitmaskclient.test;
 
 import android.test.ActivityInstrumentationTestCase2;
 import android.widget.ListView;
-import com.jayway.android.robotium.solo.Solo;
+import com.robotium.solo.Solo;
 import java.io.IOException;
 import se.leap.bitmaskclient.AboutActivity;
 import se.leap.bitmaskclient.ConfigurationWizard;
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java
index bbc3e97db955aec11e1d6b7073c7219df845a0bd..fdf4f13591eb1c07531ad57dd82b8d75bc5bfb4c 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java
@@ -7,7 +7,9 @@ import android.content.IntentFilter;
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
-import com.jayway.android.robotium.solo.Solo;
+import com.robotium.solo.Solo;
+
+import de.blinkt.openvpn.activities.DisconnectVPN;
 import se.leap.bitmaskclient.ConfigurationWizard;
 import se.leap.bitmaskclient.Dashboard;
 import se.leap.bitmaskclient.R;
@@ -38,28 +40,58 @@ public class testDashboard extends ActivityInstrumentationTestCase2<Dashboard> {
 	 * I cannot automate that dialog.
 	 */
 	public void testOnOffOpenVpn() {
-		solo.clickOnView(solo.getView(R.id.eipSwitch));
-		if(!solo.waitForText(getActivity().getString(R.string.eip_status_start_pending)))
-			fail();
-		if(!solo.waitForText(getActivity().getString(R.string.state_auth)))
-			fail();
-		if(!solo.waitForText(getActivity().getString(R.string.eip_state_connected), 1, 30*1000))
-			fail();
-		
-		solo.clickOnView(solo.getView(R.id.eipSwitch));
-		if(!solo.waitForText(getActivity().getString(R.string.eip_state_not_connected)))
-		    fail();
-		
-		/*ConnectionManager.setMobileDataEnabled(false, solo.getCurrentActivity().getApplicationContext());
-		
-		solo.clickOnView(solo.getView(R.id.eipSwitch));
-		if(!solo.waitForText(getActivity().getString(R.string.eip_status_start_pending)))
-			fail();
-		if(!solo.waitForText(getActivity().getString(R.string.state_nonetwork)))
-			fail();
-		*/
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOn();
+	    
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOff();
+	    
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOn();
+	    
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOff();
+	    
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOn();
+	    
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOff();
+
+	    solo.clickOnView(solo.getView(R.id.eipSwitch));
+	    testEipTurningOn();
+	    
+	    testEipIsOnNoNetwork();
+	    
 	}
-	
+
+    private void testEipTurningOn() {
+	if(!solo.waitForText(getActivity().getString(R.string.state_auth)))
+	    fail();
+	if(!solo.waitForText(getActivity().getString(R.string.eip_state_connected), 1, 30*1000))
+	    fail();
+	solo.sleep(2*1000);
+    }
+
+    private void testEipTurningOff() {
+	sayOkToDisconnect();
+	if(!solo.waitForText(getActivity().getString(R.string.eip_state_not_connected)))
+	    fail();
+	solo.sleep(2*1000);
+    }
+
+    private void sayOkToDisconnect() {
+	if(!solo.waitForActivity(DisconnectVPN.class))
+	    fail();
+	solo.clickOnText(getActivity().getString(android.R.string.yes));
+    }
+    
+    private void testEipIsOnNoNetwork() {
+	ConnectionManager.setMobileDataEnabled(false, solo.getCurrentActivity().getApplicationContext());
+	if(!solo.waitForText(getActivity().getString(R.string.eip_state_not_connected), 1, 15*1000))
+	    fail();
+    }
+    
     public void testLogInAndOut() {
 		long miliseconds_to_log_in = 40 * 1000;
 		solo.clickOnActionBarItem(R.id.login_button);
diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
index dd7af633ffa8c2bcd35f336133e4d640a34f231e..5549252ea3eadce2c5c180964caa87e360b31f68 100644
--- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -16,12 +16,20 @@
  */
  package se.leap.bitmaskclient;
 
+import android.app.IntentService;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.util.Base64;
+import android.util.Log;
 import java.io.DataOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
+import java.net.ConnectException;
 import java.net.CookieHandler;
 import java.net.CookieManager;
 import java.net.CookiePolicy;
@@ -41,34 +49,26 @@ import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPrivateKey;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Scanner;
-
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
-
 import org.apache.http.client.ClientProtocolException;
 import org.jboss.security.srp.SRPParameters;
 import org.json.JSONException;
 import org.json.JSONObject;
-
-import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-import android.app.IntentService;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.util.Base64;
-import android.util.Log;
+import se.leap.bitmaskclient.R;
 
 
 /**
@@ -193,7 +193,7 @@ public class ProviderAPI extends IntentService {
 					receiver.send(LOGOUT_FAILED, Bundle.EMPTY);
 				}
 		} else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) {
-				if(getNewCert(parameters)) {
+				if(updateVpnCertificate()) {
 					receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
 				} else {
 					receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
@@ -426,7 +426,7 @@ public class ProviderAPI extends IntentService {
 	parameters.put("user[password_verifier]", password_verifier);
 	Log.d(TAG, server_url);
 	Log.d(TAG, parameters.toString());
-	return sendToServer(server_url + "/users", "POST", parameters);
+	return sendToServer(server_url + "/users.json", "POST", parameters);
     }
 	
 	/**
@@ -538,16 +538,16 @@ public class ProviderAPI extends IntentService {
 			CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false;
 		}
 
-		if(!CA_CERT_DOWNLOADED)
-			current_download = downloadCACert(last_provider_main_url, last_danger_on);
-		if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
-			broadcast_progress(progress++);
-			CA_CERT_DOWNLOADED = true;
 			if(!PROVIDER_JSON_DOWNLOADED)
 				current_download = getAndSetProviderJson(last_provider_main_url, last_danger_on);
 			if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
+			    broadcast_progress(progress++);
+			    PROVIDER_JSON_DOWNLOADED = true;
+			    current_download = downloadCACert(last_danger_on);
+			    
+			    if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
 				broadcast_progress(progress++);
-				PROVIDER_JSON_DOWNLOADED = true;
+				CA_CERT_DOWNLOADED = true;
 				current_download = getAndSetEipServiceJson(); 
 				if(current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) {
 					broadcast_progress(progress++);
@@ -559,17 +559,25 @@ public class ProviderAPI extends IntentService {
 		return current_download;
 	}
 	
-	private Bundle downloadCACert(String provider_main_url, boolean danger_on) {
+	private Bundle downloadCACert(boolean danger_on) {
 		Bundle result = new Bundle();
-		String cert_string = downloadWithCommercialCA(provider_main_url + "/ca.crt", danger_on);
+		try {
+		    JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, ""));
+		    String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI);
+		    String cert_string = downloadWithCommercialCA(ca_cert_url, danger_on);
 
-	    if(validCertificate(cert_string) && setting_up_provider) {
-	    	getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit();
+		    if(validCertificate(cert_string) && setting_up_provider) {
+			getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit();
 			result.putBoolean(RESULT_KEY, true);
-		} else {
+		    } else {
 			String reason_to_fail = pickErrorMessage(cert_string);
 			result.putString(ERRORS, reason_to_fail);
 			result.putBoolean(RESULT_KEY, false);
+		    }
+		} catch (JSONException e) {
+		    String reason_to_fail = formatErrorMessage(R.string.malformed_url);
+		    result.putString(ERRORS, reason_to_fail);
+		    result.putBoolean(RESULT_KEY, false);
 		}
 		
 		return result;
@@ -697,12 +705,16 @@ public class ProviderAPI extends IntentService {
 			json_file_content = formatErrorMessage(R.string.malformed_url);
 		} catch(SocketTimeoutException e) {
 			json_file_content = formatErrorMessage(R.string.server_unreachable_message);
-		} catch (IOException e) {
+		} catch (SSLHandshakeException e) {
 			if(provider_url != null) {
-				json_file_content = downloadWithProviderCA(string_url, danger_on);
+			    json_file_content = downloadWithProviderCA(string_url, danger_on);
 			} else {
 				json_file_content = formatErrorMessage(R.string.certificate_error);
 			}
+		} catch(ConnectException e) {
+		    json_file_content = formatErrorMessage(R.string.service_is_down_error);
+		} catch (FileNotFoundException e) {
+		    json_file_content = formatErrorMessage(R.string.malformed_url);
 		} catch (Exception e) {
 			if(provider_url != null && danger_on) {
 				json_file_content = downloadWithProviderCA(string_url, danger_on);
@@ -817,7 +829,7 @@ public class ProviderAPI extends IntentService {
 			System.out.println("String ignoring certificate = " + string);
 		} catch (FileNotFoundException e) {
 			e.printStackTrace();
-			string = formatErrorMessage(R.string.server_unreachable_message);
+			string = formatErrorMessage(R.string.malformed_url);
 		} catch (IOException e) {
 			// The downloaded certificate doesn't validate our https connection.
 			e.printStackTrace();
@@ -878,16 +890,24 @@ public class ProviderAPI extends IntentService {
 		return true;
 	}
 
+    private boolean updateVpnCertificate() {
+	getNewCert();
+
+	getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(EIP.PARSED_SERIAL, 0).commit();
+	Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
+	updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
+	startService(updateEIP);
+
+	return true;
+    }
 	/**
 	 * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
 	 * 
-	 * @param task containing the type of the certificate to be downloaded
 	 * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. 
 	 */
-	private boolean getNewCert(Bundle task) {
+	private boolean getNewCert() {
 
 		try {
-			String type_of_certificate = task.getString(ConfigurationWizard.TYPE_OF_CERTIFICATE);
 			JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, ""));
 			
 			String provider_main_url = provider_json.getString(Provider.API_URL);
@@ -924,6 +944,7 @@ public class ProviderAPI extends IntentService {
 						X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString);
 						certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT);
 						getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
+						getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit();
 						
 						return true;
 					} catch (CertificateException e) {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a2c2a82f1e573ac395ec98eef3f80e8186b55ba9..a90d639656deff685d1bba75a965f1ea8403658d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,8 +17,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="se.leap.bitmaskclient"
-    android:versionCode="79"
-    android:versionName="0.5.2" >
+    android:versionCode="86"
+    android:versionName="0.5.4" >
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
index f84878916eb408533f7034ac41484f816385c6ec..a39e780ac7af9744153774b219b552b48e20d5e8 100644
--- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
+++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
@@ -110,28 +110,28 @@ public class LaunchVPN extends Activity {
 
 		}
 	}
-    
+
+
 	@Override
 	protected void onActivityResult (int requestCode, int resultCode, Intent data) {
 		super.onActivityResult(requestCode, resultCode, data);
 
 		if(requestCode==START_VPN_PROFILE) {
-			if(resultCode == Activity.RESULT_OK) {
-			    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);        
-			    boolean showlogwindow = prefs.getBoolean("showlogwindow", true);
-
-			    if(!mhideLog && showlogwindow)
-				showLogWindow();
-			    new startOpenVpnThread().start();
-			} else if (resultCode == Activity.RESULT_CANCELED) {
-				// User does not want us to start, so we just vanish
-				VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled,
-                        ConnectionStatus.LEVEL_NOTCONNECTED);
-
-				finish();
-			}
+		    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);        
+		    boolean showlogwindow = prefs.getBoolean("showlogwindow", true);
+		    
+		    if(!mhideLog && showlogwindow)
+			showLogWindow();
+		    new startOpenVpnThread().start();
+		} else if (resultCode == Activity.RESULT_CANCELED) {
+		    // User does not want us to start, so we just vanish
+		    VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled,
+						ConnectionStatus.LEVEL_NOTCONNECTED);
+
+		    finish();
 		}
 	}
+
 	void showLogWindow() {
 
 		Intent startLW = new Intent(getBaseContext(),LogWindow.class);
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index d21a085fc7b0d9690330c8f221cc8b779d492468..0166eb9806467a4724ac51afd8e922b09334c19e 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -4,10 +4,6 @@ import se.leap.bitmaskclient.R;
 
 import se.leap.bitmaskclient.R;
 
-import se.leap.bitmaskclient.EIP;
-import se.leap.bitmaskclient.Dashboard;
-import se.leap.bitmaskclient.Provider;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -95,7 +91,7 @@ public class VpnProfile implements Serializable {
     // but needs to keep wrong name to guarante loading of old
     // profiles
     public transient boolean profileDleted = false;
-    public int mAuthenticationType = TYPE_CERTIFICATES;
+    public int mAuthenticationType = TYPE_KEYSTORE;
     public String mName;
     public String mAlias;
     public String mClientCertFilename;
@@ -281,13 +277,14 @@ public class VpnProfile implements Serializable {
         switch (mAuthenticationType) {
             case VpnProfile.TYPE_USERPASS_CERTIFICATES:
                 cfg += "auth-user-pass\n";
-            case VpnProfile.TYPE_CERTIFICATES:		
-		// FIXME This is all we need...The whole switch statement can go...
-		SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
-		cfg+="<ca>\n"+preferences.getString(Provider.CA_CERT, "")+"\n</ca>\n";
-		cfg+="<key>\n"+preferences.getString(EIP.PRIVATE_KEY, "")+"\n</key>\n";
-		cfg+="<cert>\n"+preferences.getString(EIP.CERTIFICATE, "")+"\n</cert>\n";
-		
+            case VpnProfile.TYPE_CERTIFICATES:
+                // Ca
+                cfg += insertFileData("ca", mCaFilename);
+
+                // Client Cert + Key
+                cfg += insertFileData("key", mClientKeyFilename);
+                cfg += insertFileData("cert", mClientCertFilename);
+
                 break;
             case VpnProfile.TYPE_USERPASS_PKCS12:
                 cfg += "auth-user-pass\n";
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index 4fbbe165c3ef58a2e25d9b46f32e9892a8c5007a..378b6b92dcdf99097e7ae8fa05f6ea7ef0f8df4f 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -26,14 +26,6 @@ public class ConfigParser {
 
 	private boolean extraRemotesAsCustom=false;
 
-    /*
-     * TODO: We shouldn't be using this method. 
-     * We need to figure out how to use just parseConfig, probably removing parseOptions.
-     */
-    public void setDefinition(HashMap<String,Vector<Vector<String>>> args) {
-	options = args;
-    }
-    
 	public void parseConfig(Reader reader) throws IOException, ConfigParseError {
 
 
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
index b5bba5d4a51b0ab2353fb3509e9672e6674a261d..43b27212ce328c7aec8324170f392307c461b94e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
@@ -34,7 +34,6 @@ import se.leap.bitmaskclient.BuildConfig;
 import se.leap.bitmaskclient.R;
 import de.blinkt.openvpn.VpnProfile;
 import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.activities.LogWindow;
 import de.blinkt.openvpn.core.VpnStatus.ByteCountListener;
 import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
 import de.blinkt.openvpn.core.VpnStatus.StateListener;
@@ -44,6 +43,8 @@ import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
 import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
 import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
 
+import se.leap.bitmaskclient.Dashboard;
+
 public class OpenVpnService extends VpnService implements StateListener, Callback, ByteCountListener {
     public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
     public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
@@ -72,13 +73,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
     private String mLastTunCfg;
     private String mRemoteGW;
 
-    //TODO We should know if this is running or not without this method
-    public boolean isRunning() {
-	if (mStarting == true || mProcessThread != null)
-	    return true;
-	else
-	    return false;
-    }
     // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
     public static String humanReadableByteCount(long bytes, boolean mbit) {
         if (mbit)
@@ -243,7 +237,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
 
     PendingIntent getLogPendingIntent() {
         // Let the configure Button show the Log
-        Intent intent = new Intent(getBaseContext(), se.leap.bitmaskclient.Dashboard.class);
+        Intent intent = new Intent(getBaseContext(), Dashboard.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
         PendingIntent startLW = PendingIntent.getActivity(this, 0, intent, 0);
         intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
index 2f04d23524da591544a6d29e65c0c249531bfc4a..6e592121ed9c1e0cd3b1ec6b438a937cd3f269f7 100644
--- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
+++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
@@ -7,33 +7,39 @@ import se.leap.bitmaskclient.R;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.app.*;
-import android.content.*;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ListFragment;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Handler.Callback;
-import android.os.IBinder;
 import android.os.Message;
 import android.text.SpannableString;
 import android.text.format.DateFormat;
 import android.text.style.ImageSpan;
-import android.view.*;
-import android.widget.*;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemLongClickListener;
-import de.blinkt.openvpn.*;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import se.leap.bitmaskclient.Dashboard;
-import de.blinkt.openvpn.core.OpenVPNManagement;
-import de.blinkt.openvpn.core.VpnStatus;
-import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus.LogItem;
-import de.blinkt.openvpn.core.VpnStatus.LogListener;
-import de.blinkt.openvpn.core.VpnStatus.StateListener;
-import de.blinkt.openvpn.core.OpenVpnService;
-import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
-import de.blinkt.openvpn.core.ProfileManager;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.RadioGroup;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
 import org.jetbrains.annotations.Nullable;
 
 import java.text.SimpleDateFormat;
@@ -42,31 +48,29 @@ import java.util.Date;
 import java.util.Locale;
 import java.util.Vector;
 
+import de.blinkt.openvpn.LaunchVPN;
+import se.leap.bitmaskclient.R;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.activities.DisconnectVPN;
+import de.blinkt.openvpn.core.OpenVPNManagement;
+import de.blinkt.openvpn.core.OpenVpnService;
+import de.blinkt.openvpn.core.ProfileManager;
+import de.blinkt.openvpn.core.VpnStatus;
+import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
+import de.blinkt.openvpn.core.VpnStatus.LogItem;
+import de.blinkt.openvpn.core.VpnStatus.LogListener;
+import de.blinkt.openvpn.core.VpnStatus.StateListener;
+
 import static de.blinkt.openvpn.core.OpenVpnService.humanReadableByteCount;
 
+import se.leap.bitmaskclient.Dashboard;
+
 public class LogFragment extends ListFragment implements StateListener, SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener, VpnStatus.ByteCountListener {
 	private static final String LOGTIMEFORMAT = "logtimeformat";
 	private static final int START_VPN_CONFIG = 0;
     private static final String VERBOSITYLEVEL = "verbositylevel";
-    protected OpenVpnService mService;
-	private ServiceConnection mConnection = new ServiceConnection() {
 
 
-		@Override
-		public void onServiceConnected(ComponentName className,
-				IBinder service) {
-			// We've bound to LocalService, cast the IBinder and get LocalService instance
-			LocalBinder binder = (LocalBinder) service;
-			mService = binder.getService();
-		}
-
-		@Override
-		public void onServiceDisconnected(ComponentName arg0) {
-			mService =null;
-		}
-
-	};
-
     private SeekBar mLogLevelSlider;
     private LinearLayout mOptionsLayout;
     private RadioGroup mTimeRadioGroup;
@@ -425,8 +429,18 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
             Intent intent = new Intent(getActivity(),DisconnectVPN.class);
             startActivity(intent);
             return true;
-		} else if(item.getItemId()==R.id.send) {
+        } else if(item.getItemId()==R.id.send) {
 			ladapter.shareLog();
+		} else if(item.getItemId()==R.id.edit_vpn) {
+			VpnProfile lastConnectedprofile = ProfileManager.getLastConnectedVpn();
+
+			if(lastConnectedprofile!=null) {
+				Intent vprefintent = new Intent(getActivity(),Dashboard.class)
+				.putExtra(VpnProfile.EXTRA_PROFILEUUID,lastConnectedprofile.getUUIDString());
+				startActivityForResult(vprefintent,START_VPN_CONFIG);
+			} else {
+				Toast.makeText(getActivity(), R.string.log_no_last_vpn, Toast.LENGTH_LONG).show();
+			}
 		} else if(item.getItemId() == R.id.toggle_time) {
 			showHideOptionsPanel();
 		} else if(item.getItemId() == android.R.id.home) {
@@ -492,10 +506,6 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
         Intent intent = new Intent(getActivity(), OpenVpnService.class);
         intent.setAction(OpenVpnService.START_SERVICE);
 
-        getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
-
-
-
     }
 
 
@@ -531,14 +541,13 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
 		super.onActivityResult(requestCode, resultCode, data);
 	}
 
-	@Override
+
+    @Override
     public void onStop() {
 		super.onStop();
 		VpnStatus.removeStateListener(this);
         VpnStatus.removeByteCountListener(this);
 
-        if(mService!=null)
-            getActivity().unbindService(mConnection);
         getActivity().getPreferences(0).edit().putInt(LOGTIMEFORMAT, ladapter.mTimeFormat)
                                 .putInt(VERBOSITYLEVEL, ladapter.mLogLevel).apply();
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index f2763d84c5282e536ed68e581f73e02859d3bdc3..117e45d87d5b77313767e7fdfddbea724a2ad608 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -472,9 +472,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
 		} else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
         	setResult(RESULT_OK);
     		changeStatusMessage(resultCode);
-        	mProgressBar.setVisibility(ProgressBar.GONE);
+		if(mProgressBar != null)
+		    mProgressBar.setVisibility(ProgressBar.GONE);
 		if(EipServiceFragment.isEipSwitchChecked())
 		    eipStart();
+		else
+		    eipStatus.setText(R.string.eip_state_not_connected);
 		} else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
         	setResult(RESULT_CANCELED);
     		changeStatusMessage(resultCode);
@@ -496,7 +499,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
 						case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break;
 						case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.authed_secured_status); break;
 						case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break;
-						case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.anonymous_secured_status); break;
+						case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break;
 						case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break;
 						
 						}	
@@ -507,9 +510,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
 
 						case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break;
 						case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break;
-						case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.future_authed_secured_status); break;
+						case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break;
 						case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break;
-						case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.future_anonymous_secured_status); break;
+						case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break;
 						case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break;			
 						}
 					}
@@ -570,4 +573,16 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
 	startService(eip_intent);
 
     }
+
+    protected void setProgressBarVisibility(int visibility) {
+	if(mProgressBar == null)
+	    mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);	    
+	mProgressBar.setVisibility(visibility);
+    }
+
+    protected void setEipStatus(int status) {
+	if(eipStatus == null)
+	    eipStatus = (TextView) findViewById(R.id.eipStatus);
+	eipStatus.setText(status);
+    }
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java
index 59faf93f1777652ced4c28bcf90478990d635c0d..7374d5edb345f356f5d45638d0003d41d1e17440 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EIP.java
@@ -14,43 +14,56 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
- package se.leap.bitmaskclient;
+package se.leap.bitmaskclient;
+
+
 
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.Vector;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 
-import se.leap.bitmaskclient.R;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.core.ConfigParser;
-import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
-import de.blinkt.openvpn.LaunchVPN;
-import de.blinkt.openvpn.core.OpenVpnManagementThread;
-import de.blinkt.openvpn.core.OpenVpnService;
-import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
-import de.blinkt.openvpn.core.ProfileManager;
-import de.blinkt.openvpn.VpnProfile;
 import android.app.Activity;
 import android.app.IntentService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.SharedPreferences;
 import android.drm.DrmStore.Action;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ResultReceiver;
 import android.util.Log;
+import de.blinkt.openvpn.LaunchVPN;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.activities.DisconnectVPN;
+import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
+import de.blinkt.openvpn.core.ConfigParser;
+import de.blinkt.openvpn.core.OpenVpnManagementThread;
+import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
+import de.blinkt.openvpn.core.OpenVpnService;
+import de.blinkt.openvpn.core.ProfileManager;
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Vector;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import se.leap.bitmaskclient.Dashboard;
+import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.R;
 
 /**
  * EIP is the abstract base class for interacting with and managing the Encrypted
@@ -60,16 +73,19 @@ import android.util.Log;
  * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVpnService} connections.
  * 
  * @author Sean Leonard <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
  */
 public final class EIP extends IntentService {
 	
 	public final static String AUTHED_EIP = "authed eip";
+	public final static String ACTION_CHECK_CERT_VALIDITY = "se.leap.bitmaskclient.CHECK_CERT_VALIDITY";
 	public final static String ACTION_START_EIP = "se.leap.bitmaskclient.START_EIP";
 	public final static String ACTION_STOP_EIP = "se.leap.bitmaskclient.STOP_EIP";
 	public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.bitmaskclient.UPDATE_EIP_SERVICE";
 	public final static String ACTION_IS_EIP_RUNNING = "se.leap.bitmaskclient.IS_RUNNING";
 	public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION";
     	public final static String STATUS = "eip status";
+    	public final static String DATE_FROM_CERTIFICATE = "date from certificate";
 	public final static String ALLOWED_ANON = "allow_anonymous";
 	public final static String CERTIFICATE = "cert";
 	public final static String PRIVATE_KEY = "private_key";
@@ -79,8 +95,9 @@ public final class EIP extends IntentService {
 	public final static String RECEIVER_TAG = "receiverTag";
 	public final static String REQUEST_TAG = "requestTag";
 	public final static String TAG = "se.leap.bitmaskclient.EIP";
-	
-	
+
+    public final static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
+    
 	private static Context context;
 	private static ResultReceiver mReceiver;
 	private static OpenVpnService mVpnService;
@@ -104,13 +121,11 @@ public final class EIP extends IntentService {
 		context = getApplicationContext();
 		
 		updateEIPService();
-		
-		this.retreiveVpnService();
 	}
 	
 	@Override
 	public void onDestroy() {
-	    unbindService(mVpnServiceConn);
+
 	    mBound = false;
 	    
 	    super.onDestroy();
@@ -130,136 +145,70 @@ public final class EIP extends IntentService {
 			this.startEIP();
 		else if ( action == ACTION_STOP_EIP )
 			this.stopEIP();
+		else if ( action == ACTION_CHECK_CERT_VALIDITY )
+			this.checkCertValidity();
 	}
 	
 	/**
-	 * Sends an Intent to bind OpenVpnService.
-	 * Used when OpenVpnService isn't bound but might be running.
+	 * Checks the last stored status notified by ics-openvpn
+	 * Sends <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
+	 * request if it's not connected, <code>Activity.RESULT_OK</code> otherwise.
 	 */
-	private boolean retreiveVpnService() {
-		Intent bindIntent = new Intent(this,OpenVpnService.class);
-		bindIntent.setAction(OpenVpnService.START_SERVICE);
-		return bindService(bindIntent, mVpnServiceConn, BIND_AUTO_CREATE);
-	}
 	
-	private static ServiceConnection mVpnServiceConn = new ServiceConnection() {
-		@Override
-		public void onServiceConnected(ComponentName name, IBinder service) {
-			LocalBinder binder = (LocalBinder) service;
-			mVpnService = binder.getService();
-			mBound = true;
+	  private void isRunning() {
+	      Bundle resultData = new Bundle();
+	      resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
+	      int resultCode = Activity.RESULT_CANCELED;
+	      boolean is_connected = isConnected();
 
-			if (mReceiver != null && mPending != null) {
+	      resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
+                  
+	      if (mReceiver != null){
+		  mReceiver.send(resultCode, resultData);
+	      }
 
-				boolean running = mVpnService.isRunning();
-				
-				int resultCode = Activity.RESULT_CANCELED;
-				
-				if (mPending.equals(ACTION_IS_EIP_RUNNING)){
-					resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
+	      Log.d(TAG, "isRunning() = " + is_connected);
+	  }
 
-				}
-				else if (mPending.equals(ACTION_START_EIP)){
-					resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
-				}
-				else if (mPending.equals(ACTION_STOP_EIP)){
-					resultCode = (running) ? Activity.RESULT_CANCELED
-							: Activity.RESULT_OK;
-					}
-				Bundle resultData = new Bundle();
-				resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
-				mReceiver.send(resultCode, resultData);
-				
-				mPending = null;
-			}
-		}
-
-		@Override
-		public void onServiceDisconnected(ComponentName name) {
-			mBound = false;
-			
-			if (mReceiver != null){
-				Bundle resultData = new Bundle();
-				resultData.putString(REQUEST_TAG, EIP_NOTIFICATION);
-				mReceiver.send(Activity.RESULT_CANCELED, resultData);
-			}
-		}
-		
-	
-	};
-	
-	/**
-	 * Attempts to determine if OpenVpnService has an established VPN connection
-	 * through the bound ServiceConnection.  If there is no bound service, this
-	 * method will attempt to bind a running OpenVpnService and send
-	 * <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
-	 * request.
-	 * Note: If the request to bind OpenVpnService is successful, the ResultReceiver
-	 * will be notified in {@link onServiceConnected()}
-	 */
-	
-	  private void isRunning() {
-          Bundle resultData = new Bundle();
-          resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
-          int resultCode = Activity.RESULT_CANCELED;
-	  boolean is_connected = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(STATUS, "").equalsIgnoreCase("LEVEL_CONNECTED");
-          if (mBound) {
-                  resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
-                  
-                  if (mReceiver != null){
-                          mReceiver.send(resultCode, resultData);
-                  }
-          } else {
-                  mPending = ACTION_IS_EIP_RUNNING;
-                 boolean retrieved_vpn_service = retreiveVpnService();
-                 try {
-					Thread.sleep(1000);
-				} catch (InterruptedException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				}
-                 boolean running = is_connected;
-                 
-                 if (retrieved_vpn_service && running && mReceiver != null){
-                	  mReceiver.send(Activity.RESULT_OK, resultData);
-                  }
-                  else{
-                	  mReceiver.send(Activity.RESULT_CANCELED, resultData);
-                  }
-          }
-  }
+    private boolean isConnected() {
+	return getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(STATUS, "").equalsIgnoreCase("LEVEL_CONNECTED");
+    }
 	
 	/**
 	 * Initiates an EIP connection by selecting a gateway and preparing and sending an
 	 * Intent to {@link se.leap.openvpn.LaunchVPN}
 	 */
 	private void startEIP() {
-		activeGateway = selectGateway();
+	    activeGateway = selectGateway();
 		
-		Intent intent = new Intent(this,LaunchVPN.class);
-		intent.setAction(Intent.ACTION_MAIN);
-		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-		intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() );
-		intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
-		intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
-		intent.putExtra(RECEIVER_TAG, mReceiver);
-		startActivity(intent);
-		mPending = ACTION_START_EIP;
+	    if(activeGateway != null && activeGateway.mVpnProfile != null) {
+		launchActiveGateway();
+	    }
 	}
+
+    private void launchActiveGateway() {
+	Intent intent = new Intent(this,LaunchVPN.class);
+	intent.setAction(Intent.ACTION_MAIN);
+	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+	intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() );
+	intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
+	intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
+	intent.putExtra(RECEIVER_TAG, mReceiver);
+	startActivity(intent);
+	mPending = ACTION_START_EIP;
+    }
 	
 	/**
 	 * Disconnects the EIP connection gracefully through the bound service or forcefully
 	 * if there is no bound service.  Sends a message to the requesting ResultReceiver.
 	 */
 	private void stopEIP() {
-		if (mBound)
-			mVpnService.onRevoke();
-		else if(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(STATUS, "").startsWith("LEVEL_CONNECT")){
+	    if(isConnected()) {
 		    Intent disconnect_vpn = new Intent(this, DisconnectVPN.class);
 		    disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 		    startActivity(disconnect_vpn);
 		}
-			
+
 		if (mReceiver != null){
 			Bundle resultData = new Bundle();
 			resultData.putString(REQUEST_TAG, ACTION_STOP_EIP);
@@ -281,62 +230,27 @@ public final class EIP extends IntentService {
 			e.printStackTrace();
 		}
 		if(parsedEipSerial == 0) {
-			// Delete all vpn profiles
-			ProfileManager vpl = ProfileManager.getInstance(context);
-			VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]);
-			for (int current_profile = 0; current_profile < profiles.length; current_profile++){
-				vpl.removeProfile(context, profiles[current_profile]);
-			}
+		    deleteAllVpnProfiles();
 		}
-		if (eipDefinition.optInt("serial") > parsedEipSerial)
+		if (eipDefinition != null && eipDefinition.optInt("serial") > parsedEipSerial)
 			updateGateways();
 	}
-	
+
+    private void deleteAllVpnProfiles() {
+	ProfileManager vpl = ProfileManager.getInstance(context);
+	VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]);
+	for (int current_profile = 0; current_profile < profiles.length; current_profile++){
+	    vpl.removeProfile(context, profiles[current_profile]);
+	}
+    }
 	/**
 	 * Choose a gateway to connect to based on timezone from system locale data
 	 * 
 	 * @return The gateway to connect to
 	 */
 	private OVPNGateway selectGateway() {
-		// TODO Remove String arg constructor in favor of findGatewayByName(String)
-		
-		Calendar cal = Calendar.getInstance();
-		int localOffset = cal.get(Calendar.ZONE_OFFSET) / 3600000;
-		TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
-		JSONObject locationsObjects = null;
-		Iterator<String> locations = null;
-		try {
-			locationsObjects = eipDefinition.getJSONObject("locations");
-			locations = locationsObjects.keys();
-		} catch (JSONException e1) {
-			// TODO Auto-generated catch block
-			e1.printStackTrace();
-		}
-		
-		while (locations.hasNext()) {
-			String locationName = locations.next();
-			JSONObject location = null;
-			try {
-				location = locationsObjects.getJSONObject(locationName);
-				
-				// Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
-				int dist = Math.abs(localOffset - location.optInt("timezone"));
-				// Farther than 12 timezones and it's shorter around the "back"
-				if (dist > 12)
-					dist = 12 - (dist -12);  // Well i'll be.  Absolute values make equations do funny things.
-				
-				Set<String> set = offsets.get(dist);
-				if (set == null) set = new HashSet<String>();
-				set.add(locationName);
-				offsets.put(dist, set);
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-		}
-		
+		String closestLocation = closestGateway();
 		
-		String closestLocation = offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
 		JSONArray gateways = null;
 		String chosenHost = null;
 		try {
@@ -344,7 +258,7 @@ public final class EIP extends IntentService {
 			for (int i = 0; i < gateways.length(); i++) {
 				JSONObject gw = gateways.getJSONObject(i);
 				if ( gw.getString("location").equalsIgnoreCase(closestLocation) || closestLocation.isEmpty()){
-					chosenHost = gw.getString("host");
+					chosenHost = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name");
 					break;
 				}
 			}
@@ -355,6 +269,44 @@ public final class EIP extends IntentService {
 
 		return new OVPNGateway(chosenHost);
 	}
+
+    private String closestGateway() {
+	Calendar cal = Calendar.getInstance();
+	int localOffset = cal.get(Calendar.ZONE_OFFSET) / 3600000;
+	TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
+	JSONObject locationsObjects = null;
+	Iterator<String> locations = null;
+	try {
+	    locationsObjects = eipDefinition.getJSONObject("locations");
+	    locations = locationsObjects.keys();
+	} catch (JSONException e1) {
+	    // TODO Auto-generated catch block
+	    e1.printStackTrace();
+	}
+		
+	while (locations.hasNext()) {
+	    String locationName = locations.next();
+	    JSONObject location = null;
+	    try {
+		location = locationsObjects.getJSONObject(locationName);
+				
+		// Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
+		int dist = Math.abs(localOffset - location.optInt("timezone"));
+		// Farther than 12 timezones and it's shorter around the "back"
+		if (dist > 12)
+		    dist = 12 - (dist -12);  // Well i'll be.  Absolute values make equations do funny things.
+				
+		Set<String> set = offsets.get(dist);
+		if (set == null) set = new HashSet<String>();
+		set.add(locationName);
+		offsets.put(dist, set);
+	    } catch (JSONException e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	    }
+	}		
+	return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
+    }
 	
 	/**
 	 * Walk the list of gateways defined in eip-service.json and parse them into
@@ -365,35 +317,52 @@ public final class EIP extends IntentService {
 		JSONArray gatewaysDefined = null;
 		
 		try {
-			gatewaysDefined = eipDefinition.getJSONArray("gateways");
-		} catch (JSONException e1) {
-			// TODO Auto-generated catch block
-			e1.printStackTrace();
-		}
-		
-		for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
+			gatewaysDefined = eipDefinition.getJSONArray("gateways");		
+			for ( int i=0 ; i < gatewaysDefined.length(); i++ ){			
+			    JSONObject gw = null;			
+			    gw = gatewaysDefined.getJSONObject(i);
 			
-			JSONObject gw = null;
-			
-			try {
-				gw = gatewaysDefined.getJSONObject(i);
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-			
-			try {
-				if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){
-					new OVPNGateway(gw);
-				}
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
+			    if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") )
+				new OVPNGateway(gw);
 			}
+		} catch (JSONException e) {
+		    // TODO Auto-generated catch block
+		    e.printStackTrace();
 		}
+		
 		getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit();
 	}
 
+    private void checkCertValidity() {
+	String certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(CERTIFICATE, "");
+	String date_from_certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(DATE_FROM_CERTIFICATE, Calendar.getInstance().getTime().toString());
+	X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate_string);
+
+	Calendar offset_date = Calendar.getInstance();
+	try {
+	    long difference = Math.abs(certificate_date_format.parse(date_from_certificate_string).getTime() - certificate_x509.getNotAfter().getTime())/2;
+	    long current_date_millis = offset_date.getTimeInMillis();
+	    offset_date.setTimeInMillis(current_date_millis + difference);
+	    Log.d(TAG, "certificate not after = " + certificate_x509.getNotAfter());
+	} catch(ParseException e) {
+	    e.printStackTrace();
+	}
+	
+	Bundle result_data = new Bundle();
+	result_data.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY);
+	try {
+	    Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
+	    certificate_x509.checkValidity(offset_date.getTime());
+	    mReceiver.send(Activity.RESULT_OK, result_data);
+	    Log.d(TAG, "Valid certificate");
+	} catch(CertificateExpiredException e) {
+	    mReceiver.send(Activity.RESULT_CANCELED, result_data);
+	    Log.d(TAG, "Updating certificate");
+	} catch(CertificateNotYetValidException e) {
+	    mReceiver.send(Activity.RESULT_CANCELED, result_data);
+	}
+    }
+
 	/**
 	 * OVPNGateway provides objects defining gateways and their options and metadata.
 	 * Each instance contains a VpnProfile for OpenVPN specific data and member
@@ -425,7 +394,6 @@ public final class EIP extends IntentService {
 		
 		private void loadVpnProfile() {
 			ProfileManager vpl = ProfileManager.getInstance(context);
-			
 			try {
 				if ( mName == null )
 					mVpnProfile = vpl.getProfiles().iterator().next();
@@ -455,175 +423,187 @@ public final class EIP extends IntentService {
 			Collection<VpnProfile> profiles = vpl.getProfiles();
 			for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){
 				VpnProfile p = it.next();
-				try {
-					if ( p.mName.equalsIgnoreCase( gateway.getString("host") ) ){
-						it.remove();
-						vpl.removeProfile(context, p);
-					}
-				} catch (JSONException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
+				
+				if ( p.mName.equalsIgnoreCase( mName ) ) {
+				    it.remove();
+				    vpl.removeProfile(context, p);
 				}
 			}
 			
-			this.parseOptions();
 			this.createVPNProfile();
 			
-			setUniqueProfileName(vpl);
+			setUniqueProfileName();
 			vpl.addProfile(mVpnProfile);
 			vpl.saveProfile(context, mVpnProfile);
 			vpl.saveProfileList(context);
 		}
-		
-		/**
-		 * Attempts to create a unique profile name from the hostname of the gateway
-		 * 
-		 * @param profileManager
-		 */
-		private void setUniqueProfileName(ProfileManager profileManager) {
-			int i=0;
-
-			String newname;
-			try {
-				newname = mGateway.getString("host");
-				while(profileManager.getProfileByName(newname)!=null) {
-					i++;
-					if(i==1)
-						newname = getString(R.string.converted_profile);
-					else
-						newname = getString(R.string.converted_profile_i,i);
-				}
 
-				mVpnProfile.mName=newname;
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				Log.v(TAG,"Couldn't read gateway name for profile creation!");
-				e.printStackTrace();
-			}
+	    
+	    public String locationAsName() {
+		try {
+		    return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name");
+		} catch (JSONException e) {
+		    Log.v(TAG,"Couldn't read gateway name for profile creation! Returning original name = " + mName);
+		    e.printStackTrace();
+		    return (mName != null) ? mName : "";
 		}
+	    }
 
+		
 		/**
-		 * FIXME This method is really the outline of the refactoring needed in se.leap.openvpn.ConfigParser 
+		 * Attempts to create a unique profile name 
+		 * based on the location of the gateway.
 		 */
-		private void parseOptions(){
-			
-			// FIXME move these to a common API (& version) definition place, like ProviderAPI or ConfigHelper
-			String common_options = "openvpn_configuration";
-			String remote = "ip_address";
-			String ports = "ports";
-			String protos = "protocols";
-			String capabilities = "capabilities";
-			String location_key = "location";
-			String locations = "locations";
-			
-			Vector<String> arg = new Vector<String>();
-			Vector<Vector<String>> args = new Vector<Vector<String>>();
-			
-			try {
-				JSONObject def = (JSONObject) eipDefinition.get(common_options);
-				Iterator keys = def.keys();
-				Vector<Vector<String>> value = new Vector<Vector<String>>();
-				while ( keys.hasNext() ){
-					String key = keys.next().toString();
-					
-					arg.add(key);
-					for ( String word : def.getString(key).split(" ") )
-						arg.add(word);
-					value.add( (Vector<String>) arg.clone() );
-					options.put(key, (Vector<Vector<String>>) value.clone());
-					value.clear();
-					arg.clear();
-				}
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-
-            // We are always client, because the ifconfig will be received by a needed command
-            options.put("client", null);
-
-			try {
-				arg.add(remote);
-				arg.add(mGateway.getString(remote));
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-			args.add((Vector<String>) arg.clone());
-			options.put("remote", (Vector<Vector<String>>) args.clone() );
-			arg.clear();
-			args.clear();
-
-
-			
-			// try {
-			// 	arg.add(location_key);
-			// 	String locationText = "";
-			// 	locationText = eipDefinition.getJSONObject(locations).getJSONObject(mGateway.getString(location_key)).getString("name");		
-			// 	arg.add(locationText);
-			//     Log.d(TAG, "location = " + locationText);
-
-			// } catch (JSONException e) {
-			// 	// TODO Auto-generated catch block
-			// 	e.printStackTrace();
-			// }
-			// args.add((Vector<String>) arg.clone());
-			// options.put("location", (Vector<Vector<String>>) args.clone() );
-
-			// arg.clear();
-			// args.clear();
-			JSONArray protocolsJSON = null;
-			arg.add("proto");
-			try {
-				protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos);
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-			Vector<String> protocols = new Vector<String>();
-			for ( int i=0; i<protocolsJSON.length(); i++ )
-				protocols.add(protocolsJSON.optString(i));
-			if ( protocols.contains("udp"))
-				arg.add("udp");
-			else if ( protocols.contains("tcp"))
-				arg.add("tcp");
-			args.add((Vector<String>) arg.clone());
-			options.put("proto", (Vector<Vector<String>>) args.clone());
-			arg.clear();
-			args.clear();
-			
-			
-			String port = null;
-			arg.add("port");
-			try {
-				port = mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
-			} catch (JSONException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-			arg.add(port);
-			args.add((Vector<String>) arg.clone());
-			options.put("port", (Vector<Vector<String>>) args.clone());
-			args.clear();
-			arg.clear();
+		private void setUniqueProfileName() {
+		    mVpnProfile.mName = mName = locationAsName();
 		}
-		
+	    
 		/**
 		 * Create and attach the VpnProfile to our gateway object
 		 */
 		protected void createVPNProfile(){
 			try {
 				ConfigParser cp = new ConfigParser();
-				cp.setDefinition(options);
+				Log.d(TAG, configFromEipServiceDotJson());
+				Log.d(TAG, caSecretFromSharedPreferences());
+				Log.d(TAG, keySecretFromSharedPreferences());
+				Log.d(TAG, certSecretFromSharedPreferences());
+				cp.parseConfig(new StringReader(configFromEipServiceDotJson()));
+				cp.parseConfig(new StringReader(caSecretFromSharedPreferences()));
+				cp.parseConfig(new StringReader(keySecretFromSharedPreferences()));
+				cp.parseConfig(new StringReader(certSecretFromSharedPreferences()));
 				VpnProfile vp = cp.convertProfile();
+				//vp.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
 				mVpnProfile = vp;
 				Log.v(TAG,"Created VPNProfile");
 			} catch (ConfigParseError e) {
 				// FIXME We didn't get a VpnProfile!  Error handling! and log level
-				Log.v(TAG,"Error createing VPNProfile");
+				Log.v(TAG,"Error creating VPNProfile");
+				e.printStackTrace();
+			} catch (IOException e) {
+				// FIXME We didn't get a VpnProfile!  Error handling! and log level
+				Log.v(TAG,"Error creating VPNProfile");
 				e.printStackTrace();
 			}
 		}
+
+	    /**
+	     * Parses data from eip-service.json to a section of the openvpn config file
+	     */
+	    private String configFromEipServiceDotJson() {
+		String parsed_configuration = "";
+		
+		String location_key = "location";
+		String locations = "locations";
+
+		parsed_configuration += extractCommonOptionsFromEipServiceDotJson();
+		parsed_configuration += extractRemotesFromEipServiceDotJson();
+
+		return parsed_configuration;
+	    }
+
+	    private String extractCommonOptionsFromEipServiceDotJson() {
+		String common_options = "";
+		try {
+		    String common_options_key = "openvpn_configuration";
+		    JSONObject openvpn_configuration = eipDefinition.getJSONObject(common_options_key);
+		    Iterator keys = openvpn_configuration.keys();
+		    Vector<Vector<String>> value = new Vector<Vector<String>>();
+		    while ( keys.hasNext() ){
+			String key = keys.next().toString();
+					
+			common_options += key + " ";
+			for ( String word : openvpn_configuration.getString(key).split(" ") )
+			    common_options += word + " ";
+			common_options += System.getProperty("line.separator");
+			
+		    }
+		} catch (JSONException e) {
+		    // TODO Auto-generated catch block
+		    e.printStackTrace();
+		}
+
+		common_options += "client" + System.getProperty("line.separator");
+
+		return common_options;
+	    }
+		
+	    
+	    private String extractRemotesFromEipServiceDotJson() {
+		String remotes = "";
+		
+		String remote = "ip_address";
+		String remote_openvpn_keyword = "remote";
+		String ports = "ports";
+		String protos = "protocols";
+		String capabilities = "capabilities";
+		String udp = "udp";
+		
+		try {
+		    JSONArray protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos);
+		    for ( int i=0; i<protocolsJSON.length(); i++ ) {
+			String remote_line = remote_openvpn_keyword;
+			remote_line += " " + mGateway.getString(remote);
+			remote_line += " " + mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
+			remote_line += " " + protocolsJSON.optString(i);
+			if(remote_line.endsWith(udp))
+			    remotes = remotes.replaceFirst(remote_openvpn_keyword, remote_line + System.getProperty("line.separator") + remote_openvpn_keyword);
+			else
+			    remotes += remote_line;
+			remotes += System.getProperty("line.separator");
+		    }
+		} catch (JSONException e) {
+		    // TODO Auto-generated catch block
+		    e.printStackTrace();
+		}
+		
+		Log.d(TAG, "remotes = " + remotes);
+		return remotes;
+	    }
+
+	    private String caSecretFromSharedPreferences() {
+		String secret_lines = "";
+		SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
+		
+		System.getProperty("line.separator");
+		secret_lines += "<ca>";
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += preferences.getString(Provider.CA_CERT, "");
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += "</ca>";
+		
+		return secret_lines;
+	    }
+
+	    private String keySecretFromSharedPreferences() {
+		String secret_lines = "";
+		SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
+	
+		secret_lines += System.getProperty("line.separator");
+		secret_lines +="<key>";
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += preferences.getString(EIP.PRIVATE_KEY, "");
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += "</key>";
+		secret_lines += System.getProperty("line.separator");
+
+		return secret_lines;
+	    }
+
+	    private String certSecretFromSharedPreferences() {
+		String secret_lines = "";
+		SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);	
+		
+		secret_lines += System.getProperty("line.separator");
+		secret_lines +="<cert>";
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += preferences.getString(EIP.CERTIFICATE, "");
+		secret_lines += System.getProperty("line.separator");
+		secret_lines += "</cert>";
+		secret_lines += System.getProperty("line.separator");
+
+		return secret_lines;
+	    }
 	}
 
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
index 446ba1d98a2497a67eb9f45d2708b0ec47ee8ce5..5a5bb5684c21990bbc3eb66bb7aaab11b8bc1802 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
@@ -1,6 +1,10 @@
 package se.leap.bitmaskclient;
 
 import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.ProviderAPIResultReceiver;
+import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
+import se.leap.bitmaskclient.Dashboard;
+
 import de.blinkt.openvpn.activities.LogWindow;
 import de.blinkt.openvpn.core.VpnStatus;
 import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
@@ -21,6 +25,7 @@ import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.CompoundButton;
+import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.Switch;
 import android.widget.TextView;
@@ -37,9 +42,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 
 	private boolean eipAutoSwitched = true;
 	
-	private boolean mEipStartPending = false;
-
-    private boolean set_switch_off = false;
+ 	private boolean mEipStartPending = false;
 
     private static EIPReceiver mEIPReceiver;
 
@@ -96,15 +99,9 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 		super.onResume();
 
 		VpnStatus.addStateListener(this);
-		if(set_switch_off) {
-		    eipSwitch.setChecked(false);
-		    set_switch_off = false;
-		}
+		
+		eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY);
 	}
-
-    protected void setSwitchOff(boolean value) {
-	set_switch_off = value;
-    }
     
 	@Override
 	public void onPause() {
@@ -131,8 +128,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
     }
 	@Override
 	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-	    Log.d("bitmask", "onCheckChanged");
-		if (buttonView.equals(eipSwitch) && !eipAutoSwitched){
+	    if (buttonView.equals(eipSwitch) && !eipAutoSwitched){
 		    boolean allowed_anon = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).getBoolean(EIP.ALLOWED_ANON, false);
 		    String certificate = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).getString(EIP.CERTIFICATE, "");
 		    if(allowed_anon || !certificate.isEmpty()) {
@@ -173,8 +169,12 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 		    }
 		}
 		else {
-		    if(!eipSwitch.isChecked())
-			eipStatus.setText(R.string.state_noprocess);
+		    if(!eipSwitch.isChecked()) {
+			if(getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).getString(EIP.STATUS, "").equalsIgnoreCase(ConnectionStatus.LEVEL_AUTH_FAILED.toString()))
+			    startEipFromScratch();
+			else
+			    eipStatus.setText(R.string.state_noprocess);
+			}
 		}
 		eipAutoSwitched = true;
 		saveEipStatus();
@@ -198,9 +198,10 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 	 */
 	private void eipCommand(String action){
 		// TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
-		Intent vpnIntent = new Intent(action);
-		vpnIntent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver);
-		getActivity().startService(vpnIntent);
+	    Intent vpn_intent = new Intent(getActivity().getApplicationContext(), EIP.class);
+	    vpn_intent.setAction(action);
+	    vpn_intent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver);
+	    getActivity().startService(vpn_intent);
 	}
 	
 	@Override
@@ -221,7 +222,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 						mEipStartPending = false;
 					} else if ( level == ConnectionStatus.LEVEL_NONETWORK || level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED) {
 						statusMessage = getString(R.string.eip_state_not_connected);
-						getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
+						if(getActivity() != null && getActivity().findViewById(R.id.eipProgress) != null)
+						    getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
 						mEipStartPending = false;
 						switchState = false;
 					} else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) {
@@ -255,7 +257,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 		@Override
 		protected void onReceiveResult(int resultCode, Bundle resultData) {
 			super.onReceiveResult(resultCode, resultData);
-			
+		
 			String request = resultData.getString(EIP.REQUEST_TAG);
 			boolean checked = false;
 			
@@ -297,6 +299,29 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
 					checked = false;
 					break;
 				}
+			} else if (request == EIP.ACTION_CHECK_CERT_VALIDITY) {
+			    checked = eipSwitch.isChecked();
+			    
+			    switch (resultCode) {
+			    case Activity.RESULT_OK:
+				break;
+			    case Activity.RESULT_CANCELED:
+				Dashboard dashboard = (Dashboard) getActivity();
+				
+				dashboard.setProgressBarVisibility(ProgressBar.VISIBLE);
+				dashboard.setEipStatus(R.string.updating_certificate_message);
+				
+				Intent provider_API_command = new Intent(getActivity(), ProviderAPI.class);
+				if(dashboard.providerAPI_result_receiver == null) {
+				    dashboard.providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+				    dashboard.providerAPI_result_receiver.setReceiver(dashboard);
+				}
+				
+				provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
+				provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, dashboard.providerAPI_result_receiver);
+				getActivity().startService(provider_API_command);
+				break;
+			    }
 			}
 			
 			eipAutoSwitched = true;
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 216f426118197809c84490dc0777afe4479fe129..5326709f5655f1dd8961ffa0d0f5f1be6e2ecd78 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -51,6 +51,7 @@ public final class Provider implements Serializable {
 	SERVICE = "service",
 	KEY = "provider",
 	CA_CERT = "ca_cert",
+	CA_CERT_URI = "ca_cert_uri",
 	NAME = "name",
 	DESCRIPTION = "description",
 	DOMAIN = "domain",
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_vpn.png b/app/src/main/res/drawable-hdpi/ic_stat_vpn.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3547e8557444e33792b51f5868615d956f9d4b1
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_stat_vpn.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_vpn_empty_halo.png b/app/src/main/res/drawable-hdpi/ic_stat_vpn_empty_halo.png
index 7df5b670c65185b017e85707d223c04a34846e94..25f82a959a30bb6b89f21eea1dd36471fd919660 100644
Binary files a/app/src/main/res/drawable-hdpi/ic_stat_vpn_empty_halo.png and b/app/src/main/res/drawable-hdpi/ic_stat_vpn_empty_halo.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_vpn_offline.png b/app/src/main/res/drawable-hdpi/ic_stat_vpn_offline.png
index 8aa4880362defc07664f8c02441218c2934f2c74..dfb962b9f2194fa5bfdd54ea44cd17d361a3c057 100644
Binary files a/app/src/main/res/drawable-hdpi/ic_stat_vpn_offline.png and b/app/src/main/res/drawable-hdpi/ic_stat_vpn_offline.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png
deleted file mode 100644
index b5583d999bd6b3ec4a1a31aff73cd00137e3735d..0000000000000000000000000000000000000000
Binary files a/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png
new file mode 120000
index 0000000000000000000000000000000000000000..96d8d34d6cab7a4cc86c4b18ba3e88dcb5d91785
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_stat_vpn_outline.png
@@ -0,0 +1 @@
+./ic_stat_vpn_empty_halo.png
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/ic_vpn_disconnected.png b/app/src/main/res/drawable-hdpi/ic_vpn_disconnected.png
deleted file mode 100644
index dfb962b9f2194fa5bfdd54ea44cd17d361a3c057..0000000000000000000000000000000000000000
Binary files a/app/src/main/res/drawable-hdpi/ic_vpn_disconnected.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_stat_vpn.png b/app/src/main/res/drawable-ldpi/ic_stat_vpn.png
index f973015c32178ebe38a640a8ab1851478e82172f..65fc6db787bf0b607a9b4826bdb1772257b9f302 100644
Binary files a/app/src/main/res/drawable-ldpi/ic_stat_vpn.png and b/app/src/main/res/drawable-ldpi/ic_stat_vpn.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_stat_vpn_empty_halo.png b/app/src/main/res/drawable-ldpi/ic_stat_vpn_empty_halo.png
new file mode 100644
index 0000000000000000000000000000000000000000..2df0a9bd1c513d23e2bff5a22fcb9a239648dd3f
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_stat_vpn_empty_halo.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_stat_vpn_offline.png b/app/src/main/res/drawable-ldpi/ic_stat_vpn_offline.png
new file mode 100644
index 0000000000000000000000000000000000000000..22f3497e6565df5224677e895cce319ac2ce08a1
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_stat_vpn_offline.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-ldpi/ic_stat_vpn_outline.png
new file mode 120000
index 0000000000000000000000000000000000000000..482dafd3732919a7ca06cce562fd4ef2f06ee108
--- /dev/null
+++ b/app/src/main/res/drawable-ldpi/ic_stat_vpn_outline.png
@@ -0,0 +1 @@
+./ic_stat_vpn_offline.png
\ No newline at end of file
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_vpn.png b/app/src/main/res/drawable-mdpi/ic_stat_vpn.png
new file mode 100644
index 0000000000000000000000000000000000000000..7e167f84dfa4b288628da0a42419948ec73cc140
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_stat_vpn.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_vpn_empty_halo.png b/app/src/main/res/drawable-mdpi/ic_stat_vpn_empty_halo.png
index fc039a82757c1f11d23cf49482904bfc795890a5..a658d9e97425f783bb1563920fcc07717a559f7c 100644
Binary files a/app/src/main/res/drawable-mdpi/ic_stat_vpn_empty_halo.png and b/app/src/main/res/drawable-mdpi/ic_stat_vpn_empty_halo.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_vpn_offline.png b/app/src/main/res/drawable-mdpi/ic_stat_vpn_offline.png
index f31387a40862b7edb6bafad3c6ac3693c52e9ee7..f8b02bfb1ac0421fa5744035ecc0ff2d4085b1f1 100644
Binary files a/app/src/main/res/drawable-mdpi/ic_stat_vpn_offline.png and b/app/src/main/res/drawable-mdpi/ic_stat_vpn_offline.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png
deleted file mode 100644
index 052aef9d41db3123f260e7548bca5bdb305c8922..0000000000000000000000000000000000000000
Binary files a/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png
new file mode 120000
index 0000000000000000000000000000000000000000..96d8d34d6cab7a4cc86c4b18ba3e88dcb5d91785
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_stat_vpn_outline.png
@@ -0,0 +1 @@
+./ic_stat_vpn_empty_halo.png
\ No newline at end of file
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_vpn.png b/app/src/main/res/drawable-xhdpi/ic_stat_vpn.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f46be2cea5d125b9324c9aa12522a6798719767
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_stat_vpn.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_empty_halo.png b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_empty_halo.png
index 2f61e890f2d4360d8cb3382c6ce35ad64df0b6cf..f4f28ef74a6ddd062d3061c05c9154677cb1c7d9 100644
Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_empty_halo.png and b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_empty_halo.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_offline.png b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_offline.png
index e94115183fa382bf09cbd1e7d6f5d1e68f9616cc..7f44c46f90747e9a829b23d6a6deab1af47e397b 100644
Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_offline.png and b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_offline.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png
deleted file mode 100644
index 5d27240da922c161652a1b8a6487959803bf36fa..0000000000000000000000000000000000000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png
new file mode 120000
index 0000000000000000000000000000000000000000..96d8d34d6cab7a4cc86c4b18ba3e88dcb5d91785
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_stat_vpn_outline.png
@@ -0,0 +1 @@
+./ic_stat_vpn_empty_halo.png
\ No newline at end of file
diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml
index 4b3f16e06307c1da13f0c0bb7c152b00897d40e8..ccb1ea26d7701f4e48d87bfec2b5eccc4630dfc6 100644
--- a/app/src/main/res/layout/about.xml
+++ b/app/src/main/res/layout/about.xml
@@ -37,6 +37,12 @@
             android:autoLink="all"
             android:text="@string/repository_url_text" />
 
+	<TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:autoLink="all"
+            android:text="@string/leap_tracker" />
+
         <Space
             android:layout_width="match_parent"
             android:layout_height="10sp" />
diff --git a/app/src/main/res/layout/client_dashboard.xml b/app/src/main/res/layout/client_dashboard.xml
index a5387efdc046fc4fba73d0b13834372e9f78f7da..f33ac285ec5e0bfecdf0af5687bc9c4cc5153c08 100644
--- a/app/src/main/res/layout/client_dashboard.xml
+++ b/app/src/main/res/layout/client_dashboard.xml
@@ -10,44 +10,28 @@
         android:layout_width="match_parent"
         android:layout_height="40dp"
         android:background="?android:attr/selectableItemBackground" >
-    
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:gravity="center_vertical"
-            android:orientation="vertical"
-            android:paddingLeft="10dp" >
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                android:singleLine="true"
-                android:text="@string/provider_label"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:textSize="24sp" />
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center_vertical"
-            android:orientation="vertical"
-            android:paddingLeft="15dp" >
-
-            <TextView
-                android:id="@+id/providerName"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                android:singleLine="true"
-                android:text="@string/provider_label_none"
-                android:textAppearance="?android:attr/textAppearanceMedium" />
+      
+      <TextView
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+	  android:layout_marginLeft="5dp"
+          android:ellipsize="marquee"
+          android:fadingEdge="horizontal"
+          android:singleLine="true"
+          android:text="@string/provider_label"
+          android:textAppearance="?android:attr/textAppearanceMedium" />
+      
+      <TextView
+          android:id="@+id/providerName"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+	  android:layout_marginLeft="10dp"
+          android:ellipsize="marquee"
+          android:fadingEdge="horizontal"
+          android:singleLine="true"
+          android:text="@string/provider_label_none"
+          android:textAppearance="?android:attr/textAppearanceMedium" />
 
-        </LinearLayout>
     </LinearLayout>
 
     <View
diff --git a/app/src/main/res/menu/logmenu.xml b/app/src/main/res/menu/logmenu.xml
index c498eefcde73d0a86f9107688bc15f72ef1ad713..c8c9e81586b695675a20a9ec27c1b18870d6cf2e 100644
--- a/app/src/main/res/menu/logmenu.xml
+++ b/app/src/main/res/menu/logmenu.xml
@@ -33,6 +33,7 @@
             android:alphabeticShortcut="e"
             android:icon="@android:drawable/ic_menu_edit"
             android:showAsAction="withText|ifRoom"
-            android:title="@string/edit_vpn"/>
+            android:title="@string/edit_vpn"
+	    android:visible="false"/>
 
-</menu>
\ No newline at end of file
+</menu>
diff --git a/app/src/main/res/values-de/strings-icsopenvpn.xml b/app/src/main/res/values-de/strings-icsopenvpn.xml
index 9bf586855bf68dd018196b88a3e10c9e393380e8..bf115be50859ef85f19851c4c6302e3a2b566c43 100755
--- a/app/src/main/res/values-de/strings-icsopenvpn.xml
+++ b/app/src/main/res/values-de/strings-icsopenvpn.xml
@@ -62,7 +62,7 @@
   <string name="remove_vpn">VPN löschen</string>
   <string name="check_remote_tlscert">Überprüfe, ob der Server ein Zertifikat mit TLS-Servererweiterungen verwendet (--remote-cert-tls server)</string>
   <string name="check_remote_tlscert_title">TLS-Serverzertifikat erwarten</string>
-  <string name="remote_tlscn_check_summary">Server Zertifikatssubjekt überprüfen</string>
+  <string name="remote_tlscn_check_summary">Server Zertifikatssubjekt DN überprüfen</string>
   <string name="remote_tlscn_check_title">Zertifikat Namen überprüfen</string>
   <string name="enter_tlscn_dialog">Spezifizieren Sie die Methode mit welcher der DN des Serverzertifikates (z. B. C=DE, L=Paderborn, OU=Avian IP-Carrier, CN=openvpn.blinkt.de) überprüft wird.\n\nSie können den vollständigen DN oder den RDN (openvpn.blinkt.de im Beispiel) oder ein RDN-Präfix angeben.\n\nDer RDN Präfix \"Server\" erlaubt z.B. \"Server-1\" und \"Server-2\" \n\nWenn Sie das Eingabefeld leer lassen, wird der RDN gegen den Servernamen geprüft.\n\n Für weitere Details sehen Sie die Manpage von OpenVPN 2.3.1+  unter  —verify-x509-name</string>
   <string name="enter_tlscn_title">Serverzertifikat Subject</string>
@@ -84,7 +84,7 @@
   <string name="default_route_summary">Leitet allen Internet Verkehr über das VPN</string>
   <string name="use_default_title">Benutze Default Route</string>
   <string name="custom_route_message">Benutze eigene Routen. Geben Sie Zielnetzwerk im CIDR Format an. Z.b. \"10.0.0.0/8 2002::/16\" würde die Netzwerke 10.0.0.0/8 und 2002::/16 über das VPN routen.</string>
-  <string name="custom_route_message_excluded">Netze, die nicht über das VPN weitergeleitet werden sollen. Nutzt die gleiche Syntax wie die eigenen Routen.</string>
+  <string name="custom_route_message_excluded">Netze, die nicht über das VPN geleitet werden sollen. Nutzt die gleiche Syntax wie die eigenen Routen.</string>
   <string name="custom_routes_title">Eigene Routen</string>
   <string name="custom_routes_title_excluded">Ausgeschlossene Netze</string>
   <string name="log_verbosity_level">Log Detail Level</string>
@@ -312,7 +312,7 @@
   <string name="unhandled_exception_context">%3$s: %1$s\n\n%2$s</string>
   <string name="faq_system_dialog_xposed">Wenn Sie ihr Gerät gerootet haben können Sie das &lt;a href=\"http://xposed.info/\"&gt;Xposed Framework&lt;/a&gt; und das &lt;a href=\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\"&gt;VPN Dialog confirm Modul&lt;/a&gt; auf eigene Gefahr installieren.</string>
   <string name="full_licenses">Komplette Lizenzen</string>
-  <string name="blocklocal_summary">Netze, die direkt über ein lokales Interfaces erreicht werden können werden nicht über das VPN gerottet. Deaktivieren dieser Option leitet allen Verkehr, der für lokale Netzwerke bestimmt ist, über das VPN.</string>
+  <string name="blocklocal_summary">Netze, die direkt über ein lokales Interfaces erreicht werden können werden nicht über das VPN geroutet. Deaktivieren dieser Option leitet allen Verkehr, der für lokale Netzwerke bestimmt ist, über das VPN.</string>
   <string name="blocklocal_title">VPN für lokale Netzwerke umgehen</string>
   <string name="userpw_file">Datei mit Benutzername und Passwort</string>
   <string name="imported_from_file">[Importiert aus %s]</string>
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 6a9cce290dc8074f56c7267fedf3a3b391c0fb31..ec8c21ff3d308dc6b5c04e942472a994a96ed35f 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -6,4 +6,6 @@
   <string name="routes_info6">Rutas IPv6: %s</string>
   <string name="error_empty_username">El nombre de usuario no debe estar vacío.</string>
   <string name="cert_from_keystore">Conseguido el certificado de \'%s\' de almacén de claves</string>
+  <string name="repository_url_text">Código fuente disponible en https://github.com/leapcode/bitmask_android/</string>
+  <string name="leap_tracker">Tracker disponible en https://leap.se/code</string>
 </resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d7114b7340872878d73193fc647e4d29438ac77e..1dbe8fee75b489dbb691af93dc20c960c04e0de6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,7 +2,8 @@
 <resources>
 
     <string name="retry">Retry</string>
-    <string name="repository_url_text">Source code and issue tracker available at https://github.com/leapcode/bitmask_android/</string>
+    <string name="repository_url_text">Source code available at https://github.com/leapcode/bitmask_android/</string>
+    <string name="leap_tracker">Tracker available at https://leap.se/code</string>
     <string name="translation_project_text">Translations welcome and appreciated.  See our Transifex project at https://www.transifex.com/projects/p/bitmask-android/</string>
     <string name="switch_provider_menu_option">Switch provider</string>
     <string name="info">info</string>
@@ -16,9 +17,7 @@
     <string name="provider_label_none">No provider configured</string>
     <string name="eip_settings_button_description">Access EIP connection settings</string>
     <string name="status_unknown">Status unknown.</string>
-    <string name="future_anonymous_secured_status">Connection will be secure using an anonymous certificate.</string>
     <string name="anonymous_secured_status">Connection secure using an anonymous certificate.</string>
-    <string name="future_authed_secured_status">Connection will be secure using your own certificate.</string>
     <string name="authed_secured_status">Connection secure using your own certificate.</string>
     <string name="eip_service_label">Encrypted Internet</string>
     <string name="title_activity_configuration_wizard">Select a service provider</string>
@@ -52,11 +51,14 @@
     <string name="server_unreachable_message">Server is unreachable, please try again.</string>
     <string name="malformed_url">It doesn\'t seem to be a Bitmask provider.</string>
     <string name="certificate_error">This is not a trusted Bitmask provider.</string>
+    <string name="service_is_down_error">Service is down.</string>
     <string name="configuring_provider">Configuring provider</string>
     <string name="incorrectly_downloaded_certificate_message">Your anon cert was not downloaded</string>
+    <string name="updating_certificate_message">Updating EIP certificate</string>
     <string name="authenticating_message">Logging in</string>
     <string name="signingup_message">Signing up</string>
     <string name="logout_message">Logging out from this session.</string>
+    <string name="logged_out_message">Logged out.</string>
     <string name="log_out_failed_message">Didn\'t logged out.</string>
     <string name="succesful_authentication_message">Authentication succeeded.</string>
     <string name="authentication_failed_message">Authentication failed.</string>
diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml
index 50e598ac4159c3ff94b837b2a2ff15f2503bca53..f956b6bdbbf57f17054c0c1ee319914cfe09af64 100644
--- a/app/src/main/res/values/untranslatable.xml
+++ b/app/src/main/res/values/untranslatable.xml
@@ -3,7 +3,7 @@
 	<string name="app" translatable="false">Bitmask</string>
 	<string name="app_name" translatable="false">Bitmask</string>
 	
-    <string name="copyright_leapgui" translatable="false">Copyright 2012\nLEAP Encryption Access Project &lt;info@leap.se></string>
+    <string name="copyright_leapgui" translatable="false">Copyright 2012-2014\nLEAP Encryption Access Project &lt;info@leap.se></string>
     <string name="opevpn_copyright" translatable="false">Copyright © 2002–2010 OpenVPN Technologies, Inc. &lt;sales@openvpn.net>\n
 
 	  "OpenVPN" is a trademark of OpenVPN Technologies, Inc.</string>
@@ -756,6 +756,122 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
index 6d1ff879fbee6c0796fd9ffbbc1d8b41a5f3d45b..625125d8c0ed0f65a9622c508acb11d3537f6332 100644
--- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -25,6 +25,7 @@ import java.math.BigInteger;
 import java.net.CookieHandler;
 import java.net.CookieManager;
 import java.net.CookiePolicy;
+import java.net.ConnectException;
 import java.net.MalformedURLException;
 import java.net.SocketTimeoutException;
 import java.net.URISyntaxException;
@@ -32,6 +33,7 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLEncoder;
 import java.net.UnknownHostException;
+import javax.net.ssl.SSLHandshakeException;
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -41,6 +43,7 @@ import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPrivateKey;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -188,7 +191,8 @@ public class ProviderAPI extends IntentService {
 					receiver.send(LOGOUT_FAILED, Bundle.EMPTY);
 				}
 		} else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) {
-				if(getNewCert(parameters)) {
+		    Log.d(TAG, "action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)");
+				if(updateVpnCertificate()) {
 					receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
 				} else {
 					receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
@@ -421,7 +425,7 @@ public class ProviderAPI extends IntentService {
 	parameters.put("user[password_verifier]", password_verifier);
 	Log.d(TAG, server_url);
 	Log.d(TAG, parameters.toString());
-	return sendToServer(server_url + "/users", "POST", parameters);
+	return sendToServer(server_url + "/users.json", "POST", parameters);
     }
 	
 	/**
@@ -530,47 +534,57 @@ public class ProviderAPI extends IntentService {
 	 * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url.
 	 * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. 
 	 */
-	private Bundle setUpProvider(Bundle task) {
-		int progress = 0;
-		Bundle current_download = new Bundle();
+    private Bundle setUpProvider(Bundle task) {
+	int progress = 0;
+	Bundle current_download = new Bundle();
 		
-		if(task != null && task.containsKey(Provider.MAIN_URL)) {
-			last_provider_main_url = task.getString(Provider.MAIN_URL);
-			CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false;
-		}
+	if(task != null && task.containsKey(Provider.MAIN_URL)) {
+	    last_provider_main_url = task.getString(Provider.MAIN_URL);
+	    CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false;
+	}
 
-		if(!CA_CERT_DOWNLOADED)
-			current_download = downloadCACert(last_provider_main_url);
-		if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
-			broadcast_progress(progress++);
-			CA_CERT_DOWNLOADED = true;
-			if(!PROVIDER_JSON_DOWNLOADED)
-				current_download = getAndSetProviderJson(last_provider_main_url); 
-			if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
-				broadcast_progress(progress++);
-				PROVIDER_JSON_DOWNLOADED = true;
-				current_download = getAndSetEipServiceJson(); 
-				if(current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) {
-					broadcast_progress(progress++);
-					EIP_SERVICE_JSON_DOWNLOADED = true;
-				}
-			}
+	if(!PROVIDER_JSON_DOWNLOADED)
+	    current_download = getAndSetProviderJson(last_provider_main_url); 
+	if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
+	    broadcast_progress(progress++);
+	    PROVIDER_JSON_DOWNLOADED = true;
+				
+	    if(!CA_CERT_DOWNLOADED)
+		current_download = downloadCACert();
+	    if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) {
+		broadcast_progress(progress++);
+		CA_CERT_DOWNLOADED = true;
+		current_download = getAndSetEipServiceJson(); 
+		if(current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) {
+		    broadcast_progress(progress++);
+		    EIP_SERVICE_JSON_DOWNLOADED = true;
 		}
+	    }
+	}
 		
-		return current_download;
+	return current_download;
 	}
 	
-	private Bundle downloadCACert(String provider_main_url) {
+	private Bundle downloadCACert() {
 		Bundle result = new Bundle();
-		String cert_string = downloadWithCommercialCA(provider_main_url + "/ca.crt");
+		try {
+		    JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, ""));
+		    String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI);
+		    String cert_string = downloadWithCommercialCA(ca_cert_url);
+		    result.putBoolean(RESULT_KEY, true);
 
-	    if(validCertificate(cert_string) && setting_up_provider) {
-	    	getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit();
+		    if(validCertificate(cert_string) && setting_up_provider) {
+			getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit();
 			result.putBoolean(RESULT_KEY, true);
-		} else {
+		    } else {
 			String reason_to_fail = pickErrorMessage(cert_string);
 			result.putString(ERRORS, reason_to_fail);
 			result.putBoolean(RESULT_KEY, false);
+		    }
+		} catch (JSONException e) {
+		    String reason_to_fail = formatErrorMessage(R.string.malformed_url);
+		    result.putString(ERRORS, reason_to_fail);
+		    result.putBoolean(RESULT_KEY, false);
 		}
 		
 		return result;
@@ -695,14 +709,20 @@ public class ProviderAPI extends IntentService {
 		} catch (MalformedURLException e) {
 			json_file_content = formatErrorMessage(R.string.malformed_url);
 		} catch(SocketTimeoutException e) {
+		    e.printStackTrace();
 			json_file_content = formatErrorMessage(R.string.server_unreachable_message);
-		} catch (IOException e) {
+		} catch (SSLHandshakeException e) {
 			if(provider_url != null) {
 				json_file_content = downloadWithProviderCA(string_url);
 			} else {
 				json_file_content = formatErrorMessage(R.string.certificate_error);
 			}
+		} catch(ConnectException e) {
+		    json_file_content = formatErrorMessage(R.string.service_is_down_error);
+		} catch (FileNotFoundException e) {
+		    json_file_content = formatErrorMessage(R.string.malformed_url);
 		} catch (Exception e) {
+		    e.printStackTrace();
 			if(provider_url != null) {
 				json_file_content = downloadWithProviderCA(string_url);
 			}
@@ -811,7 +831,7 @@ public class ProviderAPI extends IntentService {
 			System.out.println("String ignoring certificate = " + string);
 		} catch (FileNotFoundException e) {
 			e.printStackTrace();
-			string = formatErrorMessage(R.string.server_unreachable_message);
+			string = formatErrorMessage(R.string.malformed_url);
 		} catch (IOException e) {
 			// The downloaded certificate doesn't validate our https connection.
 			e.printStackTrace();
@@ -872,16 +892,25 @@ public class ProviderAPI extends IntentService {
 		return true;
 	}
 
+    private boolean updateVpnCertificate() {
+	getNewCert();
+
+	getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(EIP.PARSED_SERIAL, 0).commit();
+	Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
+	updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
+	startService(updateEIP);
+
+	return true;
+    }
+    
 	/**
 	 * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
 	 * 
-	 * @param task containing the type of the certificate to be downloaded
 	 * @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. 
 	 */
-	private boolean getNewCert(Bundle task) {
+	private boolean getNewCert() {
 
 		try {
-			String type_of_certificate = task.getString(ConfigurationWizard.TYPE_OF_CERTIFICATE);
 			JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, ""));
 			
 			String provider_main_url = provider_json.getString(Provider.API_URL);
@@ -916,7 +945,7 @@ public class ProviderAPI extends IntentService {
 						X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString);
 						certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT);
 						getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit();
-						
+						getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit();
 						return true;
 					} catch (CertificateException e) {
 						// TODO Auto-generated catch block
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
index eead600c666781c9e63d194c865ac6b5cd51a058..16519418af97229e1daf068a4b85b201ba600f05 100644
--- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
+++ b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
@@ -108,28 +108,28 @@ public class LaunchVPN extends Activity {
 
 		}
 	}
-    
+
+
 	@Override
 	protected void onActivityResult (int requestCode, int resultCode, Intent data) {
 		super.onActivityResult(requestCode, resultCode, data);
 
 		if(requestCode==START_VPN_PROFILE) {
-			if(resultCode == Activity.RESULT_OK) {
-			    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);        
-			    boolean showlogwindow = prefs.getBoolean("showlogwindow", true);
-
-			    if(!mhideLog && showlogwindow)
-				showLogWindow();
-			    new startOpenVpnThread().start();
-			} else if (resultCode == Activity.RESULT_CANCELED) {
-				// User does not want us to start, so we just vanish
-				VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled,
-                        ConnectionStatus.LEVEL_NOTCONNECTED);
-
-				finish();
-			}
+		    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);        
+		    boolean showlogwindow = prefs.getBoolean("showlogwindow", true);
+		    
+		    if(!mhideLog && showlogwindow)
+			showLogWindow();
+		    new startOpenVpnThread().start();
+		} else if (resultCode == Activity.RESULT_CANCELED) {
+		    // User does not want us to start, so we just vanish
+		    VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled,
+						ConnectionStatus.LEVEL_NOTCONNECTED);
+
+		    finish();
 		}
 	}
+
 	void showLogWindow() {
 
 		Intent startLW = new Intent(getBaseContext(),LogWindow.class);
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 9eed03f1213cec1236d9918fd052c267b1e09f21..d351610da04e2a7cfb25fb1d95eceb67a593d755 100644
--- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -2,10 +2,6 @@ package de.blinkt.openvpn;
 
 import se.leap.bitmaskclient.R;
 
-import se.leap.bitmaskclient.EIP;
-import se.leap.bitmaskclient.Dashboard;
-import se.leap.bitmaskclient.Provider;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -93,7 +89,7 @@ public class VpnProfile implements Serializable {
     // but needs to keep wrong name to guarante loading of old
     // profiles
     public transient boolean profileDleted = false;
-    public int mAuthenticationType = TYPE_CERTIFICATES;
+    public int mAuthenticationType = TYPE_KEYSTORE;
     public String mName;
     public String mAlias;
     public String mClientCertFilename;
@@ -279,13 +275,14 @@ public class VpnProfile implements Serializable {
         switch (mAuthenticationType) {
             case VpnProfile.TYPE_USERPASS_CERTIFICATES:
                 cfg += "auth-user-pass\n";
-            case VpnProfile.TYPE_CERTIFICATES:		
-		// FIXME This is all we need...The whole switch statement can go...
-		SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
-		cfg+="<ca>\n"+preferences.getString(Provider.CA_CERT, "")+"\n</ca>\n";
-		cfg+="<key>\n"+preferences.getString(EIP.PRIVATE_KEY, "")+"\n</key>\n";
-		cfg+="<cert>\n"+preferences.getString(EIP.CERTIFICATE, "")+"\n</cert>\n";
-		
+            case VpnProfile.TYPE_CERTIFICATES:
+                // Ca
+                cfg += insertFileData("ca", mCaFilename);
+
+                // Client Cert + Key
+                cfg += insertFileData("key", mClientKeyFilename);
+                cfg += insertFileData("cert", mClientCertFilename);
+
                 break;
             case VpnProfile.TYPE_USERPASS_PKCS12:
                 cfg += "auth-user-pass\n";
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index 4fbbe165c3ef58a2e25d9b46f32e9892a8c5007a..378b6b92dcdf99097e7ae8fa05f6ea7ef0f8df4f 100644
--- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -26,14 +26,6 @@ public class ConfigParser {
 
 	private boolean extraRemotesAsCustom=false;
 
-    /*
-     * TODO: We shouldn't be using this method. 
-     * We need to figure out how to use just parseConfig, probably removing parseOptions.
-     */
-    public void setDefinition(HashMap<String,Vector<Vector<String>>> args) {
-	options = args;
-    }
-    
 	public void parseConfig(Reader reader) throws IOException, ConfigParseError {
 
 
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
index b5bba5d4a51b0ab2353fb3509e9672e6674a261d..43b27212ce328c7aec8324170f392307c461b94e 100644
--- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
+++ b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
@@ -34,7 +34,6 @@ import se.leap.bitmaskclient.BuildConfig;
 import se.leap.bitmaskclient.R;
 import de.blinkt.openvpn.VpnProfile;
 import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.activities.LogWindow;
 import de.blinkt.openvpn.core.VpnStatus.ByteCountListener;
 import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
 import de.blinkt.openvpn.core.VpnStatus.StateListener;
@@ -44,6 +43,8 @@ import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
 import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
 import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
 
+import se.leap.bitmaskclient.Dashboard;
+
 public class OpenVpnService extends VpnService implements StateListener, Callback, ByteCountListener {
     public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
     public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
@@ -72,13 +73,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
     private String mLastTunCfg;
     private String mRemoteGW;
 
-    //TODO We should know if this is running or not without this method
-    public boolean isRunning() {
-	if (mStarting == true || mProcessThread != null)
-	    return true;
-	else
-	    return false;
-    }
     // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
     public static String humanReadableByteCount(long bytes, boolean mbit) {
         if (mbit)
@@ -243,7 +237,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
 
     PendingIntent getLogPendingIntent() {
         // Let the configure Button show the Log
-        Intent intent = new Intent(getBaseContext(), se.leap.bitmaskclient.Dashboard.class);
+        Intent intent = new Intent(getBaseContext(), Dashboard.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
         PendingIntent startLW = PendingIntent.getActivity(this, 0, intent, 0);
         intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
index 1abcc54d94ec5e4018da5a7f0bf8b47b519ee7e1..d96a66a0951cb671c1bff1c0ad9fc903f8475847 100644
--- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
+++ b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
@@ -5,33 +5,39 @@ import se.leap.bitmaskclient.R;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.app.*;
-import android.content.*;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ListFragment;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Handler.Callback;
-import android.os.IBinder;
 import android.os.Message;
 import android.text.SpannableString;
 import android.text.format.DateFormat;
 import android.text.style.ImageSpan;
-import android.view.*;
-import android.widget.*;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemLongClickListener;
-import de.blinkt.openvpn.*;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import se.leap.bitmaskclient.Dashboard;
-import de.blinkt.openvpn.core.OpenVPNManagement;
-import de.blinkt.openvpn.core.VpnStatus;
-import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus.LogItem;
-import de.blinkt.openvpn.core.VpnStatus.LogListener;
-import de.blinkt.openvpn.core.VpnStatus.StateListener;
-import de.blinkt.openvpn.core.OpenVpnService;
-import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
-import de.blinkt.openvpn.core.ProfileManager;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.RadioGroup;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
 import org.jetbrains.annotations.Nullable;
 
 import java.text.SimpleDateFormat;
@@ -40,31 +46,29 @@ import java.util.Date;
 import java.util.Locale;
 import java.util.Vector;
 
+import de.blinkt.openvpn.LaunchVPN;
+import se.leap.bitmaskclient.R;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.activities.DisconnectVPN;
+import de.blinkt.openvpn.core.OpenVPNManagement;
+import de.blinkt.openvpn.core.OpenVpnService;
+import de.blinkt.openvpn.core.ProfileManager;
+import de.blinkt.openvpn.core.VpnStatus;
+import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
+import de.blinkt.openvpn.core.VpnStatus.LogItem;
+import de.blinkt.openvpn.core.VpnStatus.LogListener;
+import de.blinkt.openvpn.core.VpnStatus.StateListener;
+
 import static de.blinkt.openvpn.core.OpenVpnService.humanReadableByteCount;
 
+import se.leap.bitmaskclient.Dashboard;
+
 public class LogFragment extends ListFragment implements StateListener, SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener, VpnStatus.ByteCountListener {
 	private static final String LOGTIMEFORMAT = "logtimeformat";
 	private static final int START_VPN_CONFIG = 0;
     private static final String VERBOSITYLEVEL = "verbositylevel";
-    protected OpenVpnService mService;
-	private ServiceConnection mConnection = new ServiceConnection() {
 
 
-		@Override
-		public void onServiceConnected(ComponentName className,
-				IBinder service) {
-			// We've bound to LocalService, cast the IBinder and get LocalService instance
-			LocalBinder binder = (LocalBinder) service;
-			mService = binder.getService();
-		}
-
-		@Override
-		public void onServiceDisconnected(ComponentName arg0) {
-			mService =null;
-		}
-
-	};
-
     private SeekBar mLogLevelSlider;
     private LinearLayout mOptionsLayout;
     private RadioGroup mTimeRadioGroup;
@@ -423,8 +427,18 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
             Intent intent = new Intent(getActivity(),DisconnectVPN.class);
             startActivity(intent);
             return true;
-		} else if(item.getItemId()==R.id.send) {
+        } else if(item.getItemId()==R.id.send) {
 			ladapter.shareLog();
+		} else if(item.getItemId()==R.id.edit_vpn) {
+			VpnProfile lastConnectedprofile = ProfileManager.getLastConnectedVpn();
+
+			if(lastConnectedprofile!=null) {
+				Intent vprefintent = new Intent(getActivity(),Dashboard.class)
+				.putExtra(VpnProfile.EXTRA_PROFILEUUID,lastConnectedprofile.getUUIDString());
+				startActivityForResult(vprefintent,START_VPN_CONFIG);
+			} else {
+				Toast.makeText(getActivity(), R.string.log_no_last_vpn, Toast.LENGTH_LONG).show();
+			}
 		} else if(item.getItemId() == R.id.toggle_time) {
 			showHideOptionsPanel();
 		} else if(item.getItemId() == android.R.id.home) {
@@ -490,10 +504,6 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
         Intent intent = new Intent(getActivity(), OpenVpnService.class);
         intent.setAction(OpenVpnService.START_SERVICE);
 
-        getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
-
-
-
     }
 
 
@@ -529,14 +539,13 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
 		super.onActivityResult(requestCode, resultCode, data);
 	}
 
-	@Override
+
+    @Override
     public void onStop() {
 		super.onStop();
 		VpnStatus.removeStateListener(this);
         VpnStatus.removeByteCountListener(this);
 
-        if(mService!=null)
-            getActivity().unbindService(mConnection);
         getActivity().getPreferences(0).edit().putInt(LOGTIMEFORMAT, ladapter.mTimeFormat)
                                 .putInt(VERBOSITYLEVEL, ladapter.mLogLevel).apply();
 
diff --git a/ics-openvpn-stripped/main/src/main/res/menu/logmenu.xml b/ics-openvpn-stripped/main/src/main/res/menu/logmenu.xml
index c498eefcde73d0a86f9107688bc15f72ef1ad713..c8c9e81586b695675a20a9ec27c1b18870d6cf2e 100644
--- a/ics-openvpn-stripped/main/src/main/res/menu/logmenu.xml
+++ b/ics-openvpn-stripped/main/src/main/res/menu/logmenu.xml
@@ -33,6 +33,7 @@
             android:alphabeticShortcut="e"
             android:icon="@android:drawable/ic_menu_edit"
             android:showAsAction="withText|ifRoom"
-            android:title="@string/edit_vpn"/>
+            android:title="@string/edit_vpn"
+	    android:visible="false"/>
 
-</menu>
\ No newline at end of file
+</menu>
diff --git a/ics-openvpn-stripped/main/src/main/res/values-de/strings.xml b/ics-openvpn-stripped/main/src/main/res/values-de/strings.xml
index ef9fb9d65fb1c59b874596ae0e75223d7ef62f2f..eb6ef36eca47983f441b48e2c381f3fff88cd5c7 100755
--- a/ics-openvpn-stripped/main/src/main/res/values-de/strings.xml
+++ b/ics-openvpn-stripped/main/src/main/res/values-de/strings.xml
@@ -62,7 +62,7 @@
   <string name="remove_vpn">VPN löschen</string>
   <string name="check_remote_tlscert">Überprüfe, ob der Server ein Zertifikat mit TLS-Servererweiterungen verwendet (--remote-cert-tls server)</string>
   <string name="check_remote_tlscert_title">TLS-Serverzertifikat erwarten</string>
-  <string name="remote_tlscn_check_summary">Server Zertifikatssubjekt überprüfen</string>
+  <string name="remote_tlscn_check_summary">Server Zertifikatssubjekt DN überprüfen</string>
   <string name="remote_tlscn_check_title">Zertifikat Namen überprüfen</string>
   <string name="enter_tlscn_dialog">Spezifizieren Sie die Methode mit welcher der DN des Serverzertifikates (z. B. C=DE, L=Paderborn, OU=Avian IP-Carrier, CN=openvpn.blinkt.de) überprüft wird.\n\nSie können den vollständigen DN oder den RDN (openvpn.blinkt.de im Beispiel) oder ein RDN-Präfix angeben.\n\nDer RDN Präfix \"Server\" erlaubt z.B. \"Server-1\" und \"Server-2\" \n\nWenn Sie das Eingabefeld leer lassen, wird der RDN gegen den Servernamen geprüft.\n\n Für weitere Details sehen Sie die Manpage von OpenVPN 2.3.1+  unter  —verify-x509-name</string>
   <string name="enter_tlscn_title">Serverzertifikat Subject</string>
@@ -84,7 +84,7 @@
   <string name="default_route_summary">Leitet allen Internet Verkehr über das VPN</string>
   <string name="use_default_title">Benutze Default Route</string>
   <string name="custom_route_message">Benutze eigene Routen. Geben Sie Zielnetzwerk im CIDR Format an. Z.b. \"10.0.0.0/8 2002::/16\" würde die Netzwerke 10.0.0.0/8 und 2002::/16 über das VPN routen.</string>
-  <string name="custom_route_message_excluded">Netze, die nicht über das VPN weitergeleitet werden sollen. Nutzt die gleiche Syntax wie die eigenen Routen.</string>
+  <string name="custom_route_message_excluded">Netze, die nicht über das VPN geleitet werden sollen. Nutzt die gleiche Syntax wie die eigenen Routen.</string>
   <string name="custom_routes_title">Eigene Routen</string>
   <string name="custom_routes_title_excluded">Ausgeschlossene Netze</string>
   <string name="log_verbosity_level">Log Detail Level</string>
@@ -312,7 +312,7 @@
   <string name="unhandled_exception_context">%3$s: %1$s\n\n%2$s</string>
   <string name="faq_system_dialog_xposed">Wenn Sie ihr Gerät gerootet haben können Sie das &lt;a href=\"http://xposed.info/\"&gt;Xposed Framework&lt;/a&gt; und das &lt;a href=\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\"&gt;VPN Dialog confirm Modul&lt;/a&gt; auf eigene Gefahr installieren.</string>
   <string name="full_licenses">Komplette Lizenzen</string>
-  <string name="blocklocal_summary">Netze, die direkt über ein lokales Interfaces erreicht werden können werden nicht über das VPN gerottet. Deaktivieren dieser Option leitet allen Verkehr, der für lokale Netzwerke bestimmt ist, über das VPN.</string>
+  <string name="blocklocal_summary">Netze, die direkt über ein lokales Interfaces erreicht werden können werden nicht über das VPN geroutet. Deaktivieren dieser Option leitet allen Verkehr, der für lokale Netzwerke bestimmt ist, über das VPN.</string>
   <string name="blocklocal_title">VPN für lokale Netzwerke umgehen</string>
   <string name="userpw_file">Datei mit Benutzername und Passwort</string>
   <string name="imported_from_file">[Importiert aus %s]</string>