summaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2015-06-16 11:28:05 +0200
committerParménides GV <parmegv@sdf.org>2015-06-16 11:28:05 +0200
commit66c79953db6876ec17a7ebf50dc4fd07d24fae37 (patch)
tree67075abe6ea28f7fc7213f654b86464b13507058 /app/src/main/java
parent1f41fec6765e49838141ad29151713c7ac3dd17c (diff)
parente533cf6939e3ea4233aa8a82812f8ce5fcb565ca (diff)
Merge branch 'develop'0.9.4
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/LaunchVPN.java31
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java12
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java1
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java39
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java1
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java99
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java318
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java5
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java597
-rw-r--r--app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java2
-rw-r--r--app/src/main/java/org/spongycastle/util/encoders/Base64.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/encoders/Encoder.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemObject.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java5
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemReader.java7
-rw-r--r--app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java219
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java37
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java28
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java45
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderManager.java78
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java87
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/VpnFragment.java (renamed from app/src/main/java/se/leap/bitmaskclient/EipFragment.java)168
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java42
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java29
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java28
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java (renamed from app/src/main/java/se/leap/bitmaskclient/SessionDialog.java)31
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/User.java (renamed from app/src/main/java/se/leap/bitmaskclient/User.java)12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java127
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java181
38 files changed, 1300 insertions, 1023 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
index 0eb1d99c..90216a70 100644
--- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
+++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java
@@ -7,8 +7,6 @@ package de.blinkt.openvpn;
import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.R;
-
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
@@ -117,26 +115,29 @@ 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) {
- 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();
+ 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();
+ }
}
}
-
+
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 4f747d21..43e1b57c 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -7,8 +7,6 @@ package de.blinkt.openvpn;
import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.R;
-
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@@ -98,7 +96,7 @@ public class VpnProfile implements Serializable, Cloneable {
// variable named wrong and should haven beeen transient
// but needs to keep wrong name to guarante loading of old
// profiles
- public transient boolean profileDleted = false;
+ public transient boolean profileDeleted = false;
public int mAuthenticationType = TYPE_KEYSTORE;
public String mName;
public String mAlias;
@@ -156,7 +154,7 @@ public class VpnProfile implements Serializable, Cloneable {
public boolean mRemoteRandom=false;
public HashSet<String> mAllowedAppsVpn = new HashSet<String>();
public boolean mAllowedAppsVpnAreDisallowed = true;
-
+ public String mProfileCreator;
/* Options no long used in new profiles */
public String mServerName = "openvpn.blinkt.de";
@@ -699,7 +697,11 @@ public class VpnProfile implements Serializable, Cloneable {
protected VpnProfile clone() throws CloneNotSupportedException {
VpnProfile copy = (VpnProfile) super.clone();
copy.mUuid = UUID.randomUUID();
- copy.mConnections = mConnections.clone();
+ copy.mConnections = new Connection[mConnections.length];
+ int i=0;
+ for (Connection conn: mConnections) {
+ copy.mConnections[i++]=conn.clone();
+ }
copy.mAllowedAppsVpn = (HashSet<String>) mAllowedAppsVpn.clone();
return copy;
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java
index e525abd5..94ed8a0b 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java
@@ -54,6 +54,7 @@ class CIDRIP {
} else {
return false;
}
+
}
static long getInt(String ipaddr) {
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 5f5d486c..232c454b 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -31,6 +31,9 @@ public class ConfigParser {
public static final String CONVERTED_PROFILE = "converted Profile";
private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();
+ private String auth_user_pass_file;
+ private String crl_verify_file;
+
public void parseConfig(Reader reader) throws IOException, ConfigParseError {
@@ -114,6 +117,14 @@ public class ConfigParser {
}
+ public String getAuthUserPassFile() {
+ return auth_user_pass_file;
+ }
+
+ public String getCrlVerifyFile() {
+ return crl_verify_file;
+ }
+
enum linestate {
initial,
readin_single_quote, reading_quoted, reading_unquoted, done
@@ -572,6 +583,7 @@ public class ConfigParser {
options.put("remotetls", remotetls);
Vector<String> authuser = getOption("auth-user-pass", 0, 1);
+
if (authuser != null) {
if (noauthtypeset) {
np.mAuthenticationType = VpnProfile.TYPE_USERPASS;
@@ -581,12 +593,24 @@ public class ConfigParser {
np.mAuthenticationType = VpnProfile.TYPE_USERPASS_KEYSTORE;
}
if (authuser.size() > 1) {
- // Set option value to password get to embed later.
+ if (!authuser.get(1).startsWith(VpnProfile.INLINE_TAG))
+ auth_user_pass_file = authuser.get(1);
np.mUsername = null;
useEmbbedUserAuth(np, authuser.get(1));
}
}
+ Vector<String> crlfile = getOption("crl-verify", 1, 2);
+ if (crlfile != null) {
+ // If the 'dir' parameter is present just add it as custom option ..
+ np.mCustomConfigOptions += TextUtils.join(" ", crlfile) + "\n";
+ if (crlfile.size() == 2) {
+ // Save the filename for the config converter to add later
+ crl_verify_file = crlfile.get(1);
+ }
+ }
+
+
Pair<Connection, Connection[]> conns = parseConnectionOptions(null);
np.mConnections = conns.second;
@@ -761,6 +785,16 @@ public class ConfigParser {
}
}
+ public static void removeCRLCustomOption(VpnProfile np) {
+ String lines[] = np.mCustomConfigOptions.split("\\r?\\n");
+ Vector<String> keeplines = new Vector<>();
+ for (String l : lines) {
+ if (!l.startsWith("crl-verify "))
+ keeplines.add(l);
+ }
+ np.mCustomConfigOptions = TextUtils.join("\n", keeplines);
+ }
+
private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {
for (String option : unsupportedOptions)
if (options.containsKey(option))
@@ -772,7 +806,8 @@ public class ConfigParser {
if (options.size() > 0) {
- np.mCustomConfigOptions += "# These Options were found in the config file do not map to config settings:\n";
+ np.mCustomConfigOptions = "# These options found in the config file do not map to config settings:\n"
+ + np.mCustomConfigOptions;
for (Vector<Vector<String>> option : options.values()) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
index 56a574dc..6e9e63c5 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
@@ -38,5 +38,4 @@ public class ICSOpenVPNApplication extends Application {
//ACRA.init(this);
}
}
-
}
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 3c1ec064..f9cb9a86 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -16,7 +16,6 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
-import android.net.NetworkRequest;
import android.net.VpnService;
import android.os.Binder;
import android.os.Build;
@@ -51,8 +50,6 @@ import static de.blinkt.openvpn.core.NetworkSpace.ipAddress;
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 static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
-import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NONETWORK;
import se.leap.bitmaskclient.Dashboard;
@@ -65,7 +62,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private static final String RESUME_VPN = "se.leap.bitmaskclient.RESUME_VPN";
private static final int OPENVPN_STATUS = 1;
private static boolean mNotificationAlwaysVisible = false;
- private final Vector<String> mDnslist = new Vector<String>();
+ private final Vector<String> mDnslist = new Vector<>();
private final NetworkSpace mRoutes = new NetworkSpace();
private final NetworkSpace mRoutesv6 = new NetworkSpace();
private final IBinder mBinder = new LocalBinder();
@@ -84,7 +81,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private String mLastTunCfg;
private String mRemoteGW;
private final Object mProcessLock = new Object();
- private LollipopDeviceStateListener mLollipopDeviceStateListener;
// 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) {
@@ -238,13 +234,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
//ignore exception
- } catch (NoSuchMethodException nsm) {
- VpnStatus.logException(nsm);
- } catch (IllegalArgumentException e) {
- VpnStatus.logException(e);
- } catch (IllegalAccessException e) {
- VpnStatus.logException(e);
- } catch (InvocationTargetException e) {
+ } catch (NoSuchMethodException | IllegalArgumentException |
+ InvocationTargetException | IllegalAccessException e) {
VpnStatus.logException(e);
}
@@ -328,6 +319,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
/* The intent is null when the service has been restarted */
if (intent == null) {
mProfile = ProfileManager.getLastConnectedProfile(this, false);
+ VpnStatus.logInfo(R.string.service_restarted);
/* Got no profile, just stop */
if (mProfile == null) {
@@ -415,7 +407,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
} else {
- HashMap<String, String> env = new HashMap<String, String>();
+ HashMap<String, String> env = new HashMap<>();
processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory);
}
@@ -431,7 +423,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
ProfileManager.setConnectedVpnProfile(this, mProfile);
/* TODO: At the moment we have no way to handle asynchronous PW input
- * Fixing will also allow to handle challenge/responsee authentication */
+ * Fixing will also allow to handle challenge/response authentication */
if (mProfile.needUserPWInput(true) != 0)
return START_NOT_STICKY;
@@ -442,17 +434,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
try {
Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3");
return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
+ } catch (IllegalArgumentException | InstantiationException | InvocationTargetException |
+ NoSuchMethodException | ClassNotFoundException | IllegalAccessException e ) {
e.printStackTrace();
}
return null;
@@ -501,8 +484,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.logInfo(R.string.last_openvpn_tun_config);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN)
- {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) {
allowAllAFFamilies(builder);
}
@@ -576,6 +558,26 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
+ if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist.size() >= 1) {
+ // Check if the first DNS Server is in the VPN range
+ try {
+ ipAddress dnsServer = new ipAddress(new CIDRIP(mDnslist.get(0), 32), true);
+ boolean dnsIncluded=false;
+ for (ipAddress net : positiveIPv4Routes) {
+ if (net.containsNet(dnsServer)) {
+ dnsIncluded = true;
+ }
+ }
+ if (!dnsIncluded) {
+ String samsungwarning = String.format("Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS add a custom route to your DNS Server (%s) or change to a DNS inside your VPN range", mDnslist.get(0));
+ VpnStatus.logWarning(samsungwarning);
+ }
+ } catch (Exception e) {
+ VpnStatus.logError("Error parsing DNS Server IP: " + mDnslist.get(0));
+ }
+ }
+
+
if (mDomain != null)
builder.addSearchDomain(mDomain);
@@ -616,7 +618,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
try {
//Debug.stopMethodTracing();
ParcelFileDescriptor tun = builder.establish();
- if (tun==null)
+ if (tun == null)
throw new NullPointerException("Android establish() method returned null (Really broken network configuration?)");
return tun;
} catch (Exception e) {
@@ -636,22 +638,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
builder.allowFamily(OsConstants.AF_INET6);
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- void removeLollipopCMListener() {
- ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE);
- cm.unregisterNetworkCallback(mLollipopDeviceStateListener);
- mLollipopDeviceStateListener = null;
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- void addLollipopCMListener() {
- ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE);
- NetworkRequest.Builder nrb = new NetworkRequest.Builder();
-
- mLollipopDeviceStateListener = new LollipopDeviceStateListener();
- cm.registerNetworkCallback(nrb.build(), mLollipopDeviceStateListener);
- }
-
private void addLocalNetworksToRoutes() {
// Add local network interfaces
@@ -667,11 +653,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
intf.startsWith("tun") || intf.startsWith("rmnet"))
continue;
- if (ipAddr==null || netMask == null) {
+ if (ipAddr == null || netMask == null) {
VpnStatus.logError("Local routes are broken?! (Report to author) " + TextUtils.join("|", localRoutes));
continue;
}
-
+
if (ipAddr.equals(mLocalIP.mIp))
continue;
@@ -854,21 +840,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mDisplayBytecount = true;
mConnecttime = System.currentTimeMillis();
lowpriority = true;
- if(mProfile.mPersistTun) {
- NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- ns.cancel(OPENVPN_STATUS);
- return;
- }
- } else if (level == LEVEL_NONETWORK || level == LEVEL_NOTCONNECTED) {
- NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- ns.cancel(OPENVPN_STATUS);
- return;
- } else if (level != LEVEL_NOTCONNECTED && mConnecttime > 0) {
- mDisplayBytecount = false;
- String msg = "Traffic is blocked until the VPN becomes active.";
- String ticker = msg;
- showNotification(msg, ticker, lowpriority , 0, level);
- return;
+ String ns = Context.NOTIFICATION_SERVICE;
+ NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
+ mNotificationManager.cancel(OPENVPN_STATUS);
} else {
mDisplayBytecount = false;
}
@@ -878,8 +852,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// CONNECTED
// Does not work :(
String msg = getString(resid);
- String ticker = msg;
- showNotification(msg + " " + logmessage, ticker, lowpriority, 0, level);
+ // showNotification(msg + " " + logmessage, msg, lowpriority, 0, level);
}
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
index 1ebc0a57..086cdb44 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
@@ -5,11 +5,15 @@
package de.blinkt.openvpn.core;
-import java.io.FileNotFoundException;
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.preference.PreferenceManager;
+
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.StreamCorruptedException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -17,213 +21,173 @@ import java.util.Set;
import de.blinkt.openvpn.VpnProfile;
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.preference.PreferenceManager;
-
public class ProfileManager {
- private static final String PREFS_NAME = "VPNList";
+ private static final String PREFS_NAME = "VPNList";
+ private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile";
+ private static ProfileManager instance;
+ private static VpnProfile mLastConnectedVpn = null;
+ private HashMap<String, VpnProfile> profiles = new HashMap<>();
+ private static VpnProfile tmpprofile = null;
- private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile";
+ private static VpnProfile get(String key) {
+ if (tmpprofile != null && tmpprofile.getUUIDString().equals(key))
+ return tmpprofile;
+ if (instance == null)
+ return null;
+ return instance.profiles.get(key);
+
+ }
- private static ProfileManager instance;
+ private ProfileManager() {
+ }
+ private static void checkInstance(Context context) {
+ if (instance == null) {
+ instance = new ProfileManager();
+ instance.loadVPNList(context);
+ }
+ }
- private static VpnProfile mLastConnectedVpn=null;
- private HashMap<String,VpnProfile> profiles=new HashMap<String, VpnProfile>();
- private static VpnProfile tmpprofile=null;
+ synchronized public static ProfileManager getInstance(Context context) {
+ checkInstance(context);
+ return instance;
+ }
+ public static void setConntectedVpnProfileDisconnected(Context c) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ Editor prefsedit = prefs.edit();
+ prefsedit.putString(LAST_CONNECTED_PROFILE, null);
+ prefsedit.apply();
- private static VpnProfile get(String key) {
- if (tmpprofile!=null && tmpprofile.getUUIDString().equals(key))
- return tmpprofile;
-
- if(instance==null)
- return null;
- return instance.profiles.get(key);
-
- }
+ }
+ public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ Editor prefsedit = prefs.edit();
-
- private ProfileManager() { }
-
- private static void checkInstance(Context context) {
- if(instance == null) {
- instance = new ProfileManager();
- instance.loadVPNList(context);
- }
- }
+ prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString());
+ prefsedit.apply();
+ mLastConnectedVpn = connectedrofile;
- synchronized public static ProfileManager getInstance(Context context) {
- checkInstance(context);
- return instance;
- }
-
- public static void setConntectedVpnProfileDisconnected(Context c) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- Editor prefsedit = prefs.edit();
- prefsedit.putString(LAST_CONNECTED_PROFILE, null);
- prefsedit.apply();
-
- }
+ }
- public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- Editor prefsedit = prefs.edit();
-
- prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString());
- prefsedit.apply();
- mLastConnectedVpn=connectedrofile;
-
- }
-
- public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false);
+ boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false);
if (onBoot && !useStartOnBoot)
return null;
-
- String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null);
- if(lastConnectedProfile!=null)
- return get(c, lastConnectedProfile);
- else
- return null;
- }
-
-
-
-
- public Collection<VpnProfile> getProfiles() {
- return profiles.values();
- }
-
- public VpnProfile getProfileByName(String name) {
- for (VpnProfile vpnp : profiles.values()) {
- if(vpnp.getName().equals(name)) {
- return vpnp;
- }
- }
- return null;
- }
-
- public void saveProfileList(Context context) {
- SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE);
- Editor editor = sharedprefs.edit();
- editor.putStringSet("vpnlist", profiles.keySet());
-
- // For reasing I do not understand at all
- // Android saves my prefs file only one time
- // if I remove the debug code below :(
- int counter = sharedprefs.getInt("counter", 0);
- editor.putInt("counter", counter+1);
- editor.apply();
-
- }
-
- public void addProfile(VpnProfile profile) {
- profiles.put(profile.getUUID().toString(),profile);
-
- }
-
- public static void setTemporaryProfile(VpnProfile tmp) {
- ProfileManager.tmpprofile = tmp;
- }
-
-
- public void saveProfile(Context context,VpnProfile profile) {
- // First let basic settings save its state
-
- ObjectOutputStream vpnfile;
- try {
- vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE));
-
- vpnfile.writeObject(profile);
- vpnfile.flush();
- vpnfile.close();
- } catch (FileNotFoundException e) {
- VpnStatus.logException("saving VPN profile", e);
- throw new RuntimeException(e);
- } catch (IOException e) {
- VpnStatus.logException("saving VPN profile", e);
- throw new RuntimeException(e);
- }
- }
-
-
- private void loadVPNList(Context context) {
- profiles = new HashMap<String, VpnProfile>();
- SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE);
- Set<String> vlist = listpref.getStringSet("vpnlist", null);
- Exception exp =null;
- if(vlist==null){
- vlist = new HashSet<String>();
- }
-
- for (String vpnentry : vlist) {
- try {
- ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp"));
- VpnProfile vp = ((VpnProfile) vpnfile.readObject());
-
- // Sanity check
- if(vp==null || vp.mName==null || vp.getUUID()==null)
- continue;
+ String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null);
+ if (lastConnectedProfile != null)
+ return get(c, lastConnectedProfile);
+ else
+ return null;
+ }
- vp.upgradeProfile();
- profiles.put(vp.getUUID().toString(), vp);
- } catch (StreamCorruptedException e) {
- exp=e;
- } catch (FileNotFoundException e) {
- exp=e;
- } catch (IOException e) {
- exp=e;
- } catch (ClassNotFoundException e) {
- exp=e;
- }
- if(exp!=null) {
- VpnStatus.logException("Loading VPN List",exp);
- }
- }
- }
+ public Collection<VpnProfile> getProfiles() {
+ return profiles.values();
+ }
+
+ public VpnProfile getProfileByName(String name) {
+ for (VpnProfile vpnp : profiles.values()) {
+ if (vpnp.getName().equals(name)) {
+ return vpnp;
+ }
+ }
+ return null;
+ }
+
+ public void saveProfileList(Context context) {
+ SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
+ Editor editor = sharedprefs.edit();
+ editor.putStringSet("vpnlist", profiles.keySet());
+
+ // For reasing I do not understand at all
+ // Android saves my prefs file only one time
+ // if I remove the debug code below :(
+ int counter = sharedprefs.getInt("counter", 0);
+ editor.putInt("counter", counter + 1);
+ editor.apply();
+
+ }
+
+ public void addProfile(VpnProfile profile) {
+ profiles.put(profile.getUUID().toString(), profile);
+
+ }
- public int getNumberOfProfiles() {
- return profiles.size();
- }
+ public static void setTemporaryProfile(VpnProfile tmp) {
+ ProfileManager.tmpprofile = tmp;
+ }
+ public void saveProfile(Context context, VpnProfile profile) {
+ ObjectOutputStream vpnfile;
+ try {
+ vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"), Activity.MODE_PRIVATE));
- public void removeProfile(Context context,VpnProfile profile) {
- String vpnentry = profile.getUUID().toString();
- profiles.remove(vpnentry);
- saveProfileList(context);
- context.deleteFile(vpnentry + ".vp");
- if(mLastConnectedVpn==profile)
- mLastConnectedVpn=null;
-
- }
+ vpnfile.writeObject(profile);
+ vpnfile.flush();
+ vpnfile.close();
+ } catch (IOException e) {
+ VpnStatus.logException("saving VPN profile", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ private void loadVPNList(Context context) {
+ profiles = new HashMap<>();
+ SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
+ Set<String> vlist = listpref.getStringSet("vpnlist", null);
+ if (vlist == null) {
+ vlist = new HashSet<>();
+ }
+
+ for (String vpnentry : vlist) {
+ try {
+ ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp"));
+ VpnProfile vp = ((VpnProfile) vpnfile.readObject());
+
+ // Sanity check
+ if (vp == null || vp.mName == null || vp.getUUID() == null)
+ continue;
+
+ vp.upgradeProfile();
+ profiles.put(vp.getUUID().toString(), vp);
+ } catch (IOException | ClassNotFoundException e) {
+ VpnStatus.logException("Loading VPN List", e);
+ }
+ }
+ }
- public static VpnProfile get(Context context, String profileUUID) {
- checkInstance(context);
- return get(profileUUID);
- }
+ public void removeProfile(Context context, VpnProfile profile) {
+ String vpnentry = profile.getUUID().toString();
+ profiles.remove(vpnentry);
+ saveProfileList(context);
+ context.deleteFile(vpnentry + ".vp");
+ if (mLastConnectedVpn == profile)
+ mLastConnectedVpn = null;
+ }
+ public static VpnProfile get(Context context, String profileUUID) {
+ checkInstance(context);
+ return get(profileUUID);
+ }
- public static VpnProfile getLastConnectedVpn() {
- return mLastConnectedVpn;
- }
+ public static VpnProfile getLastConnectedVpn() {
+ return mLastConnectedVpn;
+ }
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index 73ed05bc..47cb633c 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -8,7 +8,6 @@ package de.blinkt.openvpn.core;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.os.Build;
import java.io.File;
@@ -67,14 +66,14 @@ public class VPNLaunchHelper {
public static String[] buildOpenvpnArgv(Context c) {
- Vector<String> args = new Vector<String>();
+ Vector<String> args = new Vector<>();
// Add fixed paramenters
//args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
args.add(writeMiniVPN(c));
args.add("--config");
- args.add(c.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
+ args.add(getConfigFilePath(c));
return args.toArray(new String[args.size()]);
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
index ffc8097d..62a60643 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
@@ -6,6 +6,7 @@
package de.blinkt.openvpn.core;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -14,10 +15,10 @@ import android.content.pm.Signature;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import se.leap.bitmaskclient.R;
+import android.text.TextUtils;
import java.io.ByteArrayInputStream;
-import java.io.FileNotFoundException;
+import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.MessageDigest;
@@ -32,28 +33,30 @@ import java.util.Locale;
import java.util.UnknownFormatConversionException;
import java.util.Vector;
+import se.leap.bitmaskclient.R;
+
public class VpnStatus {
- public static LinkedList<LogItem> logbuffer;
+ public static LinkedList<LogItem> logbuffer;
- private static Vector<LogListener> logListener;
- private static Vector<StateListener> stateListener;
- private static Vector<ByteCountListener> byteCountListener;
+ private static Vector<LogListener> logListener;
+ private static Vector<StateListener> stateListener;
+ private static Vector<ByteCountListener> byteCountListener;
- private static String mLaststatemsg="";
+ private static String mLaststatemsg = "";
- private static String mLaststate = "NOPROCESS";
+ private static String mLaststate = "NOPROCESS";
- private static int mLastStateresid=R.string.state_noprocess;
+ private static int mLastStateresid = R.string.state_noprocess;
- private static long mlastByteCount[]={0,0,0,0};
+ private static long mlastByteCount[] = {0, 0, 0, 0};
- public static void logException(LogLevel ll, String context, Exception e) {
+ public static void logException(LogLevel ll, String context, Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
LogItem li;
- if (context !=null) {
+ if (context != null) {
li = new LogItem(ll, R.string.unhandled_exception_context, e.getMessage(), sw.toString(), context);
} else {
li = new LogItem(ll, R.string.unhandled_exception, e.getMessage(), sw.toString());
@@ -71,18 +74,16 @@ public class VpnStatus {
private static final int MAXLOGENTRIES = 1000;
- public static final String MANAGMENT_PREFIX = "M:";
-
public enum ConnectionStatus {
LEVEL_CONNECTED,
LEVEL_VPNPAUSED,
LEVEL_CONNECTING_SERVER_REPLIED,
LEVEL_CONNECTING_NO_SERVER_REPLY_YET,
LEVEL_NONETWORK,
- LEVEL_NOTCONNECTED,
- LEVEL_AUTH_FAILED,
- LEVEL_WAITING_FOR_USER_INPUT,
- UNKNOWN_LEVEL
+ LEVEL_NOTCONNECTED,
+ LEVEL_AUTH_FAILED,
+ LEVEL_WAITING_FOR_USER_INPUT,
+ UNKNOWN_LEVEL
}
public enum LogLevel {
@@ -93,6 +94,7 @@ public class VpnStatus {
DEBUG(4);
protected int mValue;
+
LogLevel(int value) {
mValue = value;
}
@@ -103,59 +105,64 @@ public class VpnStatus {
public static LogLevel getEnumByValue(int value) {
switch (value) {
- case 1: return INFO;
- case 2: return ERROR;
- case 3: return WARNING;
- case 4: return DEBUG;
- default: return null;
+ case 1:
+ return INFO;
+ case 2:
+ return ERROR;
+ case 3:
+ return WARNING;
+ case 4:
+ return DEBUG;
+ default:
+ return null;
}
}
}
// keytool -printcert -jarfile de.blinkt.openvpn_85.apk
- public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109};
- public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43};
- public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57};
+ public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109};
+ public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43};
+ public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57};
public static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104};
- private static ConnectionStatus mLastLevel=ConnectionStatus.LEVEL_NOTCONNECTED;
+ private static ConnectionStatus mLastLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
- static {
- logbuffer = new LinkedList<LogItem>();
- logListener = new Vector<VpnStatus.LogListener>();
- stateListener = new Vector<VpnStatus.StateListener>();
- byteCountListener = new Vector<VpnStatus.ByteCountListener>();
- logInformation();
- }
+ static {
+ logbuffer = new LinkedList<>();
+ logListener = new Vector<>();
+ stateListener = new Vector<>();
+ byteCountListener = new Vector<>();
+ logInformation();
+ }
- public static class LogItem implements Parcelable {
+ public static class LogItem implements Parcelable {
- private Object [] mArgs = null;
- private String mMessage = null;
- private int mRessourceId;
- // Default log priority
- LogLevel mLevel = LogLevel.INFO;
- private long logtime = System.currentTimeMillis();
+ private Object[] mArgs = null;
+ private String mMessage = null;
+ private int mRessourceId;
+ // Default log priority
+ LogLevel mLevel = LogLevel.INFO;
+ private long logtime = System.currentTimeMillis();
private int mVerbosityLevel = -1;
- private LogItem(int ressourceId, Object[] args) {
- mRessourceId = ressourceId;
- mArgs = args;
- }
+ private LogItem(int ressourceId, Object[] args) {
+ mRessourceId = ressourceId;
+ mArgs = args;
+ }
public LogItem(LogLevel level, int verblevel, String message) {
- mMessage=message;
+ mMessage = message;
mLevel = level;
mVerbosityLevel = verblevel;
}
@Override
- public int describeContents() {
- return 0;
- }
+ public int describeContents() {
+ return 0;
+ }
@Override
@@ -169,65 +176,65 @@ public class VpnStatus {
dest.writeLong(logtime);
}
- public LogItem(Parcel in) {
- mArgs = in.readArray(Object.class.getClassLoader());
- mMessage = in.readString();
- mRessourceId = in.readInt();
- mLevel = LogLevel.getEnumByValue(in.readInt());
+ public LogItem(Parcel in) {
+ mArgs = in.readArray(Object.class.getClassLoader());
+ mMessage = in.readString();
+ mRessourceId = in.readInt();
+ mLevel = LogLevel.getEnumByValue(in.readInt());
mVerbosityLevel = in.readInt();
- logtime = in.readLong();
- }
+ logtime = in.readLong();
+ }
- public static final Parcelable.Creator<LogItem> CREATOR
- = new Parcelable.Creator<LogItem>() {
- public LogItem createFromParcel(Parcel in) {
- return new LogItem(in);
- }
+ public static final Parcelable.Creator<LogItem> CREATOR
+ = new Parcelable.Creator<LogItem>() {
+ public LogItem createFromParcel(Parcel in) {
+ return new LogItem(in);
+ }
- public LogItem[] newArray(int size) {
- return new LogItem[size];
- }
- };
+ public LogItem[] newArray(int size) {
+ return new LogItem[size];
+ }
+ };
- public LogItem(LogLevel loglevel,int ressourceId, Object... args) {
+ public LogItem(LogLevel loglevel, int ressourceId, Object... args) {
mRessourceId = ressourceId;
- mArgs =args;
+ mArgs = args;
mLevel = loglevel;
}
- public LogItem(LogLevel loglevel, String msg) {
- mLevel = loglevel;
- mMessage = msg;
- }
+ public LogItem(LogLevel loglevel, String msg) {
+ mLevel = loglevel;
+ mMessage = msg;
+ }
- public LogItem(LogLevel loglevel, int ressourceId) {
- mRessourceId =ressourceId;
- mLevel = loglevel;
- }
+ public LogItem(LogLevel loglevel, int ressourceId) {
+ mRessourceId = ressourceId;
+ mLevel = loglevel;
+ }
- public String getString(Context c) {
+ public String getString(Context c) {
try {
- if(mMessage !=null) {
- return mMessage;
- } else {
- if(c!=null) {
- if(mRessourceId==R.string.mobile_info)
- return getMobileInfoString(c);
- if(mArgs == null)
- return c.getString(mRessourceId);
- else
- return c.getString(mRessourceId,mArgs);
- } else {
- String str = String.format(Locale.ENGLISH,"Log (no context) resid %d", mRessourceId);
- if(mArgs !=null)
- for(Object o:mArgs)
- str += "|" + o.toString();
-
- return str;
- }
- }
+ if (mMessage != null) {
+ return mMessage;
+ } else {
+ if (c != null) {
+ if (mRessourceId == R.string.mobile_info)
+ return getMobileInfoString(c);
+ if (mArgs == null)
+ return c.getString(mRessourceId);
+ else
+ return c.getString(mRessourceId, mArgs);
+ } else {
+ String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId);
+ if (mArgs != null)
+ str += TextUtils.join("|", mArgs);
+
+
+ return str;
+ }
+ }
} catch (UnknownFormatConversionException e) {
if (c != null)
throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null));
@@ -235,68 +242,66 @@ public class VpnStatus {
throw e;
} catch (java.util.FormatFlagsConversionMismatchException e) {
if (c != null)
- throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null),e.getConversion());
+ throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion());
else
throw e;
}
- }
+ }
- public LogLevel getLogLevel()
- {
+ public LogLevel getLogLevel() {
return mLevel;
}
// The lint is wrong here
- @SuppressLint("StringFormatMatches")
- private String getMobileInfoString(Context c) {
- c.getPackageManager();
- String apksign="error getting package signature";
-
- String version="error getting version";
- try {
- Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] der = cert.getEncoded();
- md.update(der);
- byte[] digest = md.digest();
-
- if (Arrays.equals(digest, officalkey))
- apksign = c.getString(R.string.official_build);
- else if (Arrays.equals(digest, officaldebugkey))
- apksign = c.getString(R.string.debug_build);
- else if (Arrays.equals(digest, amazonkey))
- apksign = "amazon version";
- else if (Arrays.equals(digest, fdroidkey))
+ @SuppressLint("StringFormatMatches")
+ private String getMobileInfoString(Context c) {
+ c.getPackageManager();
+ String apksign = "error getting package signature";
+
+ String version = "error getting version";
+ try {
+ Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] der = cert.getEncoded();
+ md.update(der);
+ byte[] digest = md.digest();
+
+ if (Arrays.equals(digest, officalkey))
+ apksign = c.getString(R.string.official_build);
+ else if (Arrays.equals(digest, officaldebugkey))
+ apksign = c.getString(R.string.debug_build);
+ else if (Arrays.equals(digest, amazonkey))
+ apksign = "amazon version";
+ else if (Arrays.equals(digest, fdroidkey))
apksign = "F-Droid built and signed version";
else
- apksign = c.getString(R.string.built_by,cert.getSubjectX500Principal().getName());
+ apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName());
- PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
- version = packageinfo.versionName;
+ PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
+ version = packageinfo.versionName;
- } catch (NameNotFoundException e) {
- } catch (CertificateException e) {
- } catch (NoSuchAlgorithmException e) {
- }
+ } catch (NameNotFoundException | CertificateException |
+ NoSuchAlgorithmException ignored) {
+ }
- Object[] argsext = Arrays.copyOf(mArgs, mArgs.length+2);
- argsext[argsext.length-1]=apksign;
- argsext[argsext.length-2]=version;
+ Object[] argsext = Arrays.copyOf(mArgs, mArgs.length + 2);
+ argsext[argsext.length - 1] = apksign;
+ argsext[argsext.length - 2] = version;
- return c.getString(R.string.mobile_info_extended, argsext);
+ return c.getString(R.string.mobile_info_extended, argsext);
- }
+ }
- public long getLogtime() {
- return logtime;
- }
+ public long getLogtime() {
+ return logtime;
+ }
public int getVerbosityLevel() {
- if (mVerbosityLevel==-1) {
+ if (mVerbosityLevel == -1) {
// Hack:
// For message not from OpenVPN, report the status level as log level
return mLevel.getInt();
@@ -305,90 +310,93 @@ public class VpnStatus {
}
}
+ public void saveLogToDisk(Context c) {
+
+ File logOut = new File(c.getCacheDir(), "log.xml");
+
+ }
+
+ public interface LogListener {
+ void newLog(LogItem logItem);
+ }
+
+ public interface StateListener {
+ void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level);
+ }
+
+ public interface ByteCountListener {
+ void updateByteCount(long in, long out, long diffIn, long diffOut);
+ }
+
+ public synchronized static void logMessage(LogLevel level, String prefix, String message) {
+ newLogItem(new LogItem(level, prefix + message));
+
+ }
+
+ public synchronized static void clearLog() {
+ logbuffer.clear();
+ logInformation();
+ }
+
+ private static void logInformation() {
+ logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT);
+ }
+
+ public synchronized static void addLogListener(LogListener ll) {
+ logListener.add(ll);
+ }
+
+ public synchronized static void removeLogListener(LogListener ll) {
+ logListener.remove(ll);
+ }
+
+ public synchronized static void addByteCountListener(ByteCountListener bcl) {
+ bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]);
+ byteCountListener.add(bcl);
+ }
+ public synchronized static void removeByteCountListener(ByteCountListener bcl) {
+ byteCountListener.remove(bcl);
+ }
+
+
+ public synchronized static void addStateListener(StateListener sl) {
+ if (!stateListener.contains(sl)) {
+ stateListener.add(sl);
+ if (mLaststate != null)
+ sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel);
+ }
+ }
- public interface LogListener {
- void newLog(LogItem logItem);
- }
-
- public interface StateListener {
- void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level);
- }
-
- public interface ByteCountListener {
- void updateByteCount(long in, long out, long diffIn, long diffOut);
- }
-
- public synchronized static void logMessage(LogLevel level,String prefix, String message)
- {
- newLogItem(new LogItem(level, prefix + message));
-
- }
-
- public synchronized static void clearLog() {
- logbuffer.clear();
- logInformation();
- }
-
- private static void logInformation() {
- logInfo(R.string.mobile_info,Build.MODEL, Build.BOARD,Build.BRAND,Build.VERSION.SDK_INT);
- }
-
- public synchronized static void addLogListener(LogListener ll){
- logListener.add(ll);
- }
-
- public synchronized static void removeLogListener(LogListener ll) {
- logListener.remove(ll);
- }
-
- public synchronized static void addByteCountListener(ByteCountListener bcl) {
- bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]);
- byteCountListener.add(bcl);
- }
-
- public synchronized static void removeByteCountListener(ByteCountListener bcl) {
- byteCountListener.remove(bcl);
- }
-
-
- public synchronized static void addStateListener(StateListener sl){
- if(!stateListener.contains(sl)){
- stateListener.add(sl);
- if(mLaststate!=null)
- sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel);
- }
- }
-
- private static int getLocalizedState(String state){
- if (state.equals("CONNECTING"))
- return R.string.state_connecting;
- else if (state.equals("WAIT"))
- return R.string.state_wait;
- else if (state.equals("AUTH"))
- return R.string.state_auth;
- else if (state.equals("GET_CONFIG"))
- return R.string.state_get_config;
- else if (state.equals("ASSIGN_IP"))
- return R.string.state_assign_ip;
- else if (state.equals("ADD_ROUTES"))
- return R.string.state_add_routes;
- else if (state.equals("CONNECTED"))
- return R.string.state_connected;
- else if (state.equals("DISCONNECTED"))
- return R.string.state_disconnected;
- else if (state.equals("RECONNECTING"))
- return R.string.state_reconnecting;
- else if (state.equals("EXITING"))
- return R.string.state_exiting;
- else if (state.equals("RESOLVE"))
- return R.string.state_resolve;
- else if (state.equals("TCP_CONNECT"))
- return R.string.state_tcp_connect;
- else
- return R.string.unknown_state;
-
- }
+ private static int getLocalizedState(String state) {
+ if (state.equals("CONNECTING"))
+ return R.string.state_connecting;
+ else if (state.equals("WAIT"))
+ return R.string.state_wait;
+ else if (state.equals("AUTH"))
+ return R.string.state_auth;
+ else if (state.equals("GET_CONFIG"))
+ return R.string.state_get_config;
+ else if (state.equals("ASSIGN_IP"))
+ return R.string.state_assign_ip;
+ else if (state.equals("ADD_ROUTES"))
+ return R.string.state_add_routes;
+ else if (state.equals("CONNECTED"))
+ return R.string.state_connected;
+ else if (state.equals("DISCONNECTED"))
+ return R.string.state_disconnected;
+ else if (state.equals("RECONNECTING"))
+ return R.string.state_reconnecting;
+ else if (state.equals("EXITING"))
+ return R.string.state_exiting;
+ else if (state.equals("RESOLVE"))
+ return R.string.state_resolve;
+ else if (state.equals("TCP_CONNECT"))
+ return R.string.state_tcp_connect;
+ else
+ return R.string.unknown_state;
+
+ }
public static void updateStatePause(OpenVPNManagement.pauseReason pauseReason) {
switch (pauseReason) {
@@ -405,88 +413,84 @@ public class VpnStatus {
}
- private static ConnectionStatus getLevel(String state){
- String[] noreplyet = {"CONNECTING","WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"};
- String[] reply = {"AUTH","GET_CONFIG","ASSIGN_IP","ADD_ROUTES"};
- String[] connected = {"CONNECTED"};
- String[] notconnected = {"DISCONNECTED", "EXITING"};
-
- for(String x:noreplyet)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
-
- for(String x:reply)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED;
+ private static ConnectionStatus getLevel(String state) {
+ String[] noreplyet = {"CONNECTING", "WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"};
+ String[] reply = {"AUTH", "GET_CONFIG", "ASSIGN_IP", "ADD_ROUTES"};
+ String[] connected = {"CONNECTED"};
+ String[] notconnected = {"DISCONNECTED", "EXITING"};
- for(String x:connected)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTED;
+ for (String x : noreplyet)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
- for(String x:notconnected)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_NOTCONNECTED;
+ for (String x : reply)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED;
- return ConnectionStatus.UNKNOWN_LEVEL;
+ for (String x : connected)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTED;
- }
+ for (String x : notconnected)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_NOTCONNECTED;
+ return ConnectionStatus.UNKNOWN_LEVEL;
+ }
- public synchronized static void removeStateListener(StateListener sl) {
- stateListener.remove(sl);
- }
+ public synchronized static void removeStateListener(StateListener sl) {
+ stateListener.remove(sl);
+ }
- synchronized public static LogItem[] getlogbuffer() {
+ synchronized public static LogItem[] getlogbuffer() {
- // The stoned way of java to return an array from a vector
- // brought to you by eclipse auto complete
- return logbuffer.toArray(new LogItem[logbuffer.size()]);
+ // The stoned way of java to return an array from a vector
+ // brought to you by eclipse auto complete
+ return logbuffer.toArray(new LogItem[logbuffer.size()]);
- }
+ }
- public static void updateStateString (String state, String msg) {
- int rid = getLocalizedState(state);
- ConnectionStatus level = getLevel(state);
- updateStateString(state, msg, rid, level);
- }
+ public static void updateStateString(String state, String msg) {
+ int rid = getLocalizedState(state);
+ ConnectionStatus level = getLevel(state);
+ updateStateString(state, msg, rid, level);
+ }
- public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) {
+ public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) {
// Workound for OpenVPN doing AUTH and wait and being connected
// Simply ignore these state
if (mLastLevel == ConnectionStatus.LEVEL_CONNECTED &&
- (state.equals("WAIT") || state.equals("AUTH")))
- {
- newLogItem(new LogItem((LogLevel.DEBUG), String.format("Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s",state,level.toString(),msg)));
+ (state.equals("WAIT") || state.equals("AUTH"))) {
+ newLogItem(new LogItem((LogLevel.DEBUG), String.format("Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s", state, level.toString(), msg)));
return;
}
- mLaststate= state;
- mLaststatemsg = msg;
- mLastStateresid = resid;
- mLastLevel = level;
-
+ mLaststate = state;
+ mLaststatemsg = msg;
+ mLastStateresid = resid;
+ mLastLevel = level;
for (StateListener sl : stateListener) {
- sl.updateState(state,msg,resid,level);
- }
+ sl.updateState(state, msg, resid, level);
+ }
//newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg)));
- }
+ }
- public static void logInfo(String message) {
- newLogItem(new LogItem(LogLevel.INFO, message));
- }
+ public static void logInfo(String message) {
+ newLogItem(new LogItem(LogLevel.INFO, message));
+ }
public static void logDebug(String message) {
newLogItem(new LogItem(LogLevel.DEBUG, message));
}
public static void logInfo(int resourceId, Object... args) {
- newLogItem(new LogItem(LogLevel.INFO, resourceId, args));
- }
+ newLogItem(new LogItem(LogLevel.INFO, resourceId, args));
+ }
public static void logDebug(int resourceId, Object... args) {
newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args));
@@ -494,19 +498,19 @@ public class VpnStatus {
private synchronized static void newLogItem(LogItem logItem) {
- logbuffer.addLast(logItem);
- if(logbuffer.size()>MAXLOGENTRIES)
- logbuffer.removeFirst();
+ logbuffer.addLast(logItem);
+ if (logbuffer.size() > MAXLOGENTRIES)
+ logbuffer.removeFirst();
- for (LogListener ll : logListener) {
- ll.newLog(logItem);
- }
- }
+ for (LogListener ll : logListener) {
+ ll.newLog(logItem);
+ }
+ }
- public static void logError(String msg) {
- newLogItem(new LogItem(LogLevel.ERROR, msg));
+ public static void logError(String msg) {
+ newLogItem(new LogItem(LogLevel.ERROR, msg));
- }
+ }
public static void logWarning(int resourceId, Object... args) {
newLogItem(new LogItem(LogLevel.WARNING, resourceId, args));
@@ -518,11 +522,12 @@ public class VpnStatus {
public static void logError(int resourceId) {
- newLogItem(new LogItem(LogLevel.ERROR, resourceId));
- }
- public static void logError(int resourceId, Object... args) {
- newLogItem(new LogItem(LogLevel.ERROR, resourceId, args));
- }
+ newLogItem(new LogItem(LogLevel.ERROR, resourceId));
+ }
+
+ public static void logError(int resourceId, Object... args) {
+ newLogItem(new LogItem(LogLevel.ERROR, resourceId, args));
+ }
public static void logMessageOpenVPN(LogLevel level, int ovpnlevel, String message) {
newLogItem(new LogItem(level, ovpnlevel, message));
@@ -531,19 +536,17 @@ public class VpnStatus {
public static synchronized void updateByteCount(long in, long out) {
- long lastIn = mlastByteCount[0];
- long lastOut = mlastByteCount[1];
- long diffIn = mlastByteCount[2] = in - lastIn;
- long diffOut = mlastByteCount[3] = out - lastOut;
-
-
-
- mlastByteCount = new long[] {in,out,diffIn,diffOut};
- for(ByteCountListener bcl:byteCountListener){
- bcl.updateByteCount(in, out, diffIn,diffOut);
- }
- }
+ long lastIn = mlastByteCount[0];
+ long lastOut = mlastByteCount[1];
+ long diffIn = mlastByteCount[2] = in - lastIn;
+ long diffOut = mlastByteCount[3] = out - lastOut;
+
+ mlastByteCount = new long[]{in, out, diffIn, diffOut};
+ for (ByteCountListener bcl : byteCountListener) {
+ bcl.updateByteCount(in, out, diffIn, diffOut);
+ }
+ }
}
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 92bf9ad3..2a75c15e 100644
--- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
+++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
@@ -5,8 +5,6 @@
package de.blinkt.openvpn.fragments;
-import se.leap.bitmaskclient.R;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
diff --git a/app/src/main/java/org/spongycastle/util/encoders/Base64.java b/app/src/main/java/org/spongycastle/util/encoders/Base64.java
index 87bd80a0..0993e7be 100644
--- a/app/src/main/java/org/spongycastle/util/encoders/Base64.java
+++ b/app/src/main/java/org/spongycastle/util/encoders/Base64.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.encoders;
import java.io.ByteArrayOutputStream;
diff --git a/app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java b/app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java
index 84060707..4248bb8b 100644
--- a/app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java
+++ b/app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.encoders;
import java.io.IOException;
diff --git a/app/src/main/java/org/spongycastle/util/encoders/Encoder.java b/app/src/main/java/org/spongycastle/util/encoders/Encoder.java
index 106c36b7..2007ac3e 100644
--- a/app/src/main/java/org/spongycastle/util/encoders/Encoder.java
+++ b/app/src/main/java/org/spongycastle/util/encoders/Encoder.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.encoders;
import java.io.IOException;
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java b/app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
index 0127ca0c..b9474ed3 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
import java.io.IOException;
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java b/app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
index 4adb815e..6d655c87 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
public class PemHeader
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemObject.java b/app/src/main/java/org/spongycastle/util/io/pem/PemObject.java
index 6f7c79c5..59186e09 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemObject.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemObject.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
import java.util.ArrayList;
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java b/app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
index 1a8cea6d..ddce091c 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
public interface PemObjectGenerator
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemReader.java b/app/src/main/java/org/spongycastle/util/io/pem/PemReader.java
index cbbebab9..0b3b55c4 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemReader.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemReader.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
import java.io.BufferedReader;
@@ -49,7 +54,7 @@ public class PemReader
{
String line;
String endMarker = END + type;
- StringBuffer buf = new StringBuffer();
+ StringBuilder buf = new StringBuilder();
List headers = new ArrayList();
while ((line = readLine()) != null)
diff --git a/app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java b/app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
index f5a6a363..25730efd 100644
--- a/app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
+++ b/app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2012-2014 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
package org.spongycastle.util.io.pem;
import java.io.BufferedWriter;
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index ee64a1b3..bdc36e89 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -29,11 +29,10 @@ import org.jetbrains.annotations.*;
import org.json.*;
import java.net.*;
-import java.util.*;
import butterknife.*;
-import de.blinkt.openvpn.activities.*;
import se.leap.bitmaskclient.eip.*;
+import se.leap.bitmaskclient.userstatus.*;
/**
* The main user facing Activity of Bitmask Android, consisting of status, controls,
@@ -42,7 +41,7 @@ import se.leap.bitmaskclient.eip.*;
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author parmegv
*/
-public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver, Observer {
+public class Dashboard extends Activity implements ProviderAPIResultReceiver.Receiver {
protected static final int CONFIGURE_LEAP = 0;
protected static final int SWITCH_PROVIDER = 1;
@@ -62,14 +61,10 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
@InjectView(R.id.providerName)
TextView provider_name;
- @InjectView(R.id.user_session_status)
- TextView user_session_status_text_view;
- @InjectView(R.id.user_session_status_progress)
- ProgressBar user_session_status_progress_bar;
-
- EipFragment eip_fragment;
- private Provider provider;
- private UserSessionStatus user_session_status;
+
+ VpnFragment eip_fragment;
+ UserStatusFragment user_status_fragment;
+ private static Provider provider = new Provider();
public ProviderAPIResultReceiver providerAPI_result_receiver;
private boolean switching_provider;
@@ -78,21 +73,23 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
super.onCreate(savedInstanceState);
app = this;
- user_session_status = UserSessionStatus.getInstance();
- user_session_status.addObserver(this);
PRNGFixes.apply();
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
handleVersion();
+ User.init(getString(R.string.default_username));
+
+ ProviderAPICommand.initialize(this);
+ providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), this);
restoreProvider(savedInstanceState);
- if (provider == null || provider.getName().isEmpty())
+ if (!provider.isConfigured())
startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
else {
buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
- restoreSessionStatus(savedInstanceState);
+ user_status_fragment.restoreSessionStatus(savedInstanceState);
}
}
@@ -101,32 +98,20 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
if (savedInstanceState.containsKey(Provider.KEY))
provider = savedInstanceState.getParcelable(Provider.KEY);
}
- if (provider == null && preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false))
+ if (!provider.isConfigured() && preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false))
provider = getSavedProviderFromSharedPreferences();
}
- private void restoreSessionStatus(Bundle savedInstanceState) {
- if (savedInstanceState != null)
- if (savedInstanceState.containsKey(UserSessionStatus.TAG)) {
- UserSessionStatus.SessionStatus status = (UserSessionStatus.SessionStatus) savedInstanceState.getSerializable(UserSessionStatus.TAG);
- user_session_status.updateStatus(status);
- }
- }
-
@Override
protected void onSaveInstanceState(@NotNull Bundle outState) {
- if (provider != null)
- outState.putParcelable(Provider.KEY, provider);
- if (user_session_status_text_view != null && user_session_status_text_view.getVisibility() == TextView.VISIBLE)
- outState.putSerializable(UserSessionStatus.TAG, user_session_status.sessionStatus());
-
+ outState.putParcelable(Provider.KEY, provider);
super.onSaveInstanceState(outState);
}
private Provider getSavedProviderFromSharedPreferences() {
- Provider provider = null;
+ Provider provider = new Provider();
try {
- provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, "")));
+ provider.setUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
@@ -161,12 +146,12 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
providerToPreferences(provider);
buildDashboard(false);
- invalidateOptionsMenu();
+ invalidateOptionsMenuOnUiThread();
if (data.hasExtra(SessionDialog.TAG)) {
sessionDialog(Bundle.EMPTY);
}
- } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) {
+ } else if (resultCode == RESULT_CANCELED && data != null && data.hasExtra(ACTION_QUIT)) {
finish();
} else
configErrorDialog();
@@ -213,33 +198,35 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
ButterKnife.inject(this);
provider_name.setText(provider.getDomain());
+
+ user_status_fragment = new UserStatusFragment();
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(Provider.ALLOW_REGISTRATION, provider.allowsRegistration());
+ user_status_fragment.setArguments(bundle);
+ fragment_manager.replace(R.id.user_status_fragment, user_status_fragment, UserStatusFragment.TAG);
+
if (provider.hasEIP()) {
- fragment_manager.removePreviousFragment(EipFragment.TAG);
- eip_fragment = new EipFragment();
+ fragment_manager.removePreviousFragment(VpnFragment.TAG);
+ eip_fragment = new VpnFragment();
if (hide_and_turn_on_eip) {
preferences.edit().remove(Dashboard.START_ON_BOOT).apply();
Bundle arguments = new Bundle();
- arguments.putBoolean(EipFragment.START_ON_BOOT, true);
+ arguments.putBoolean(VpnFragment.START_ON_BOOT, true);
if (eip_fragment != null) eip_fragment.setArguments(arguments);
}
- fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
+ fragment_manager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG);
if (hide_and_turn_on_eip) {
onBackPressed();
}
}
- handleNewUserSessionStatus(user_session_status);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (provider.allowsRegistration()) {
menu.findItem(R.id.signup_button).setVisible(true);
-
- boolean logged_in = User.loggedIn();
- menu.findItem(R.id.login_button).setVisible(!logged_in);
- menu.findItem(R.id.logout_button).setVisible(logged_in);
}
return true;
}
@@ -261,15 +248,9 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
return true;
case R.id.switch_provider:
switching_provider = true;
- if (LeapSRPSession.loggedIn()) logOut();
+ if (User.loggedIn()) user_status_fragment.logOut();
else switchProvider();
return true;
- case R.id.login_button:
- sessionDialog(Bundle.EMPTY);
- return true;
- case R.id.logout_button:
- logOut();
- return true;
case R.id.signup_button:
sessionDialog(Bundle.EMPTY);
return true;
@@ -284,131 +265,22 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
}
public void showLog() {
- Intent startLW = new Intent(getContext(), LogWindow.class);
- startActivity(startLW);
- }
-
- @Override
- public void signUp(String username, String password) {
- User.setUserName(username);
- Bundle parameters = bundlePassword(password);
- providerApiCommand(parameters, 0, ProviderAPI.SIGN_UP);
- }
-
- @Override
- public void logIn(String username, String password) {
- User.setUserName(username);
- Bundle parameters = bundlePassword(password);
- providerApiCommand(parameters, 0, ProviderAPI.LOG_IN);
- }
-
- public void logOut() {
- providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.LOG_OUT);
- }
-
- @Override
- public void update(Observable observable, Object data) {
- if (observable instanceof UserSessionStatus) {
- UserSessionStatus status = (UserSessionStatus) observable;
- handleNewUserSessionStatus(status);
- }
- }
-
- private void handleNewUserSessionStatus(UserSessionStatus status) {
- user_session_status = status;
- if (provider.allowsRegistration()) {
- if (user_session_status.inProgress())
- showUserSessionProgressBar();
- else
- hideUserSessionProgressBar();
- changeSessionStatusMessage(user_session_status.toString());
- invalidateOptionsMenu();
- }
- }
-
- private void changeSessionStatusMessage(final String message) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- user_session_status_text_view.setText(message);
- }
- });
- }
-
- private void showUserSessionProgressBar() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- user_session_status_progress_bar.setVisibility(ProgressBar.VISIBLE);
- }
- });
- }
-
- private void hideUserSessionProgressBar() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- user_session_status_progress_bar.setVisibility(ProgressBar.GONE);
- }
- });
+ LogWindowWrapper log_window_wrapper = LogWindowWrapper.getInstance(getContext());
+ log_window_wrapper.showLog();
}
- protected void downloadVpnCertificate() {
- boolean is_authenticated = LeapSRPSession.loggedIn();
+ public void downloadVpnCertificate() {
+ boolean is_authenticated = User.loggedIn();
boolean allowed_anon = preferences.getBoolean(Constants.ALLOWED_ANON, false);
if (allowed_anon || is_authenticated)
- providerApiCommand(Bundle.EMPTY, R.string.downloading_certificate_message, ProviderAPI.DOWNLOAD_CERTIFICATE);
+ ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_CERTIFICATE, providerAPI_result_receiver);
else
sessionDialog(Bundle.EMPTY);
-
- }
-
- private Bundle bundlePassword(String password) {
- Bundle parameters = new Bundle();
- if (!password.isEmpty())
- parameters.putString(SessionDialog.PASSWORD, password);
- return parameters;
- }
-
- protected void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) {
- if (eip_fragment != null && progressbar_message_resId != 0) {
- eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE);
- setStatusMessage(progressbar_message_resId);
- }
-
- Intent command = prepareProviderAPICommand(parameters, providerApi_action);
- startService(command);
- }
-
- private Intent prepareProviderAPICommand(Bundle parameters, String action) {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- Intent command = new Intent(this, ProviderAPI.class);
-
- command.putExtra(ProviderAPI.PARAMETERS, parameters);
- command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
- command.setAction(action);
- return command;
- }
-
- public void cancelLoginOrSignup() {
- EipStatus.getInstance().setConnectedOrDisconnected();
}
public void sessionDialog(Bundle resultData) {
-
FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
-
- DialogFragment newFragment = new SessionDialog();
- if (provider.getName().equalsIgnoreCase("riseup")) {
- resultData = resultData == Bundle.EMPTY ? new Bundle() : resultData;
- resultData.putBoolean(SessionDialog.ERRORS.RISEUP_WARNING.toString(), true);
- }
- if (resultData != null && !resultData.isEmpty()) {
- newFragment.setArguments(resultData);
- }
- newFragment.show(transaction, SessionDialog.TAG);
+ SessionDialog.getInstance(provider, resultData).show(transaction, SessionDialog.TAG);
}
private void switchProvider() {
@@ -424,7 +296,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) {
String username = resultData.getString(SessionDialog.USERNAME);
String password = resultData.getString(SessionDialog.PASSWORD);
- logIn(username, password);
+ user_status_fragment.logIn(username, password);
} else if (resultCode == ProviderAPI.FAILED_SIGNUP) {
sessionDialog(resultData);
} else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) {
@@ -437,7 +309,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
setResult(RESULT_CANCELED);
} else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
eip_fragment.updateEipService();
- eip_fragment.handleNewVpnCertificate();
setResult(RESULT_OK);
} else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
setResult(RESULT_CANCELED);
@@ -449,18 +320,24 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
}
}
- private void setStatusMessage(int string_resId) {
- if (eip_fragment != null && eip_fragment.status_message != null)
- eip_fragment.status_message.setText(string_resId);
- }
-
public static Context getContext() {
return app;
}
+ public static Provider getProvider() { return provider; }
+
@Override
public void startActivityForResult(Intent intent, int requestCode) {
intent.putExtra(Dashboard.REQUEST_CODE, requestCode);
super.startActivityForResult(intent, requestCode);
}
+
+ public void invalidateOptionsMenuOnUiThread() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ invalidateOptionsMenu();
+ }
+ });
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java b/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java
new file mode 100644
index 00000000..8daa7d8c
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java
@@ -0,0 +1,37 @@
+package se.leap.bitmaskclient;
+
+import java.net.*;
+
+public class DefaultedURL {
+ private URL DEFAULT_URL;
+ private String default_url = "https://example.net";
+
+ private URL url;
+
+ public DefaultedURL() {
+ try {
+ DEFAULT_URL = new URL(default_url);
+ url = DEFAULT_URL;
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isDefault() { return url.equals(DEFAULT_URL); }
+
+ public void setUrl(URL url) {
+ this.url = url;
+ }
+
+ public String getDomain() {
+ return url.getHost();
+ }
+
+ public URL getUrl() {
+ return url;
+ }
+
+ public String toString() {
+ return url.toString();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
index b961350e..49cf3774 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
@@ -42,7 +42,6 @@ public class LeapSRPSession {
final public static String AUTHORIZATION_HEADER = "Authorization";
final public static String TAG = "Leap SRP session class tag";
- private User user;
private SRPParameters params;
private String username;
private String password;
@@ -338,7 +337,7 @@ public class LeapSRPSession {
return token;
}
- protected static boolean loggedIn() {
+ public static boolean loggedIn() {
return !token.isEmpty();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java b/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java
new file mode 100644
index 00000000..2476f6a4
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java
@@ -0,0 +1,28 @@
+package se.leap.bitmaskclient;
+
+import android.content.*;
+
+import de.blinkt.openvpn.activities.*;
+
+public class LogWindowWrapper {
+ private static LogWindowWrapper instance;
+
+ private static String TAG = LogWindowWrapper.class.getName();
+ private Context context;
+
+ public LogWindowWrapper(Context context) {
+ this.context = context;
+ }
+
+ public void showLog() {
+ Intent startLW = new Intent(context, LogWindow.class);
+ startLW.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(startLW);
+ }
+
+ public static LogWindowWrapper getInstance(Context context) {
+ if(instance == null)
+ instance = new LogWindowWrapper(context);
+ return instance;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index ee06a586..559b47d1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -30,8 +30,9 @@ import java.util.*;
*/
public final class Provider implements Parcelable {
- private JSONObject definition; // Represents our Provider's provider.json
- private URL main_url;
+ private JSONObject definition = new JSONObject(); // Represents our Provider's provider.json
+ private DefaultedURL main_url = new DefaultedURL();
+ private String certificate_pin = "";
final public static String
API_URL = "api_uri",
@@ -58,12 +59,15 @@ public final class Provider implements Parcelable {
private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
protected static final String[] API_EIP_TYPES = {"openvpn"};
+ public Provider() { }
+
public Provider(URL main_url) {
- this.main_url = main_url;
+ this.main_url.setUrl(main_url);
}
- public Provider(File provider_file) {
-
+ public Provider(URL main_url, String certificate_pin) {
+ this.main_url.setUrl(main_url);
+ this.certificate_pin = certificate_pin;
}
public static final Parcelable.Creator<Provider> CREATOR
@@ -79,17 +83,23 @@ public final class Provider implements Parcelable {
private Provider(Parcel in) {
try {
- main_url = new URL(in.readString());
+ main_url.setUrl(new URL(in.readString()));
String definition_string = in.readString();
- if (definition_string != null)
+ if (!definition_string.isEmpty())
definition = new JSONObject((definition_string));
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (JSONException e) {
+ } catch (MalformedURLException | JSONException e) {
e.printStackTrace();
}
}
+ public boolean isConfigured() {
+ return !main_url.isDefault() && definition.length() > 0;
+ }
+
+ protected void setUrl(URL url) {
+ main_url.setUrl(url);
+ }
+
protected void define(JSONObject provider_json) {
definition = provider_json;
}
@@ -99,14 +109,16 @@ public final class Provider implements Parcelable {
}
protected String getDomain() {
- return main_url.getHost();
+ return main_url.getDomain();
}
- protected URL mainUrl() {
+ protected DefaultedURL mainUrl() {
return main_url;
}
- protected String getName() {
+ protected String certificatePin() { return certificate_pin; }
+
+ public String getName() {
// Should we pass the locale in, or query the system here?
String lang = Locale.getDefault().getLanguage();
String name = "";
@@ -116,7 +128,7 @@ public final class Provider implements Parcelable {
else throw new JSONException("Provider not defined");
} catch (JSONException e) {
if (main_url != null) {
- String host = main_url.getHost();
+ String host = main_url.getDomain();
name = host.substring(0, host.indexOf("."));
}
}
@@ -179,7 +191,8 @@ public final class Provider implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int i) {
- parcel.writeString(main_url.toString());
+ if(main_url != null)
+ parcel.writeString(main_url.toString());
if (definition != null)
parcel.writeString(definition.toString());
}
@@ -188,7 +201,7 @@ public final class Provider implements Parcelable {
public boolean equals(Object o) {
if (o instanceof Provider) {
Provider p = (Provider) o;
- return p.mainUrl().getHost().equals(mainUrl().getHost());
+ return p.mainUrl().getDomain().equals(mainUrl().getDomain());
} else return false;
}
@@ -204,6 +217,6 @@ public final class Provider implements Parcelable {
@Override
public int hashCode() {
- return mainUrl().getHost().hashCode();
+ return mainUrl().getDomain().hashCode();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
new file mode 100644
index 00000000..0e4cfe8a
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
@@ -0,0 +1,45 @@
+package se.leap.bitmaskclient;
+
+import android.content.*;
+import android.os.*;
+
+import org.jetbrains.annotations.*;
+
+public class ProviderAPICommand {
+ private static Context context;
+
+ private static String action;
+ private static Bundle parameters;
+ private static ResultReceiver result_receiver;
+
+ public static void initialize(Context context) {
+ ProviderAPICommand.context = context;
+ }
+
+ private static boolean isInitialized() {
+ return context != null;
+ }
+
+ public static void execute(Bundle parameters, @NotNull String action, @NotNull ResultReceiver result_receiver) throws IllegalStateException {
+ if(!isInitialized()) throw new IllegalStateException();
+
+ ProviderAPICommand.action = action;
+ ProviderAPICommand.parameters = parameters;
+ ProviderAPICommand.result_receiver = result_receiver;
+
+ Intent intent = setUpIntent();
+ context.startService(intent);
+ }
+
+ private static Intent setUpIntent() {
+ Intent command = new Intent(context, ProviderAPI.class);
+
+ command.setAction(action);
+ command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ command.putExtra(ProviderAPI.RECEIVER_KEY, result_receiver);
+
+ return command;
+ }
+
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
index 533e5caf..9b880f89 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
@@ -26,8 +26,9 @@ import android.os.*;
public class ProviderAPIResultReceiver extends ResultReceiver {
private Receiver mReceiver;
- public ProviderAPIResultReceiver(Handler handler) {
+ public ProviderAPIResultReceiver(Handler handler, Receiver receiver) {
super(handler);
+ setReceiver(receiver);
// TODO Auto-generated constructor stub
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
index 40fe8b5a..13ef9b80 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
@@ -28,7 +28,8 @@ public class ProviderManager implements AdapteeCollection<Provider> {
if (instance == null)
instance = new ProviderManager(assets_manager);
- instance.addCustomProviders(external_files_dir);
+ if(external_files_dir != null)
+ instance.addCustomProviders(external_files_dir);
return instance;
}
@@ -49,11 +50,14 @@ public class ProviderManager implements AdapteeCollection<Provider> {
Set<Provider> providers = new HashSet<Provider>();
try {
for (String file : relative_file_paths) {
- String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file));
- providers.add(new Provider(new URL(main_url)));
+ InputStream provider_file = assets_manager.open(directory + "/" + file);
+ String main_url = extractMainUrlFromInputStream(provider_file);
+ String certificate_pin = extractCertificatePinFromInputStream(provider_file);
+ if(certificate_pin.isEmpty())
+ providers.add(new Provider(new URL(main_url)));
+ else
+ providers.add(new Provider(new URL(main_url), certificate_pin));
}
- } catch (MalformedURLException e) {
- e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
@@ -75,36 +79,50 @@ public class ProviderManager implements AdapteeCollection<Provider> {
String main_url = extractMainUrlFromInputStream(new FileInputStream(external_files_dir.getAbsolutePath() + "/" + file));
providers.add(new Provider(new URL(main_url)));
}
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
+ } catch (MalformedURLException | FileNotFoundException e) {
e.printStackTrace();
}
return providers;
}
- private String extractMainUrlFromInputStream(InputStream input_stream_file_contents) {
+ private String extractMainUrlFromInputStream(InputStream input_stream) {
String main_url = "";
- byte[] bytes = new byte[0];
+
+ JSONObject file_contents = inputStreamToJson(input_stream);
+ if(file_contents != null)
+ main_url = file_contents.optString(Provider.MAIN_URL);
+ return main_url;
+ }
+
+ private String extractCertificatePinFromInputStream(InputStream input_stream) {
+ String certificate_pin = "";
+
+ JSONObject file_contents = inputStreamToJson(input_stream);
+ if(file_contents != null)
+ certificate_pin = file_contents.optString(Provider.CA_CERT_FINGERPRINT);
+
+ return certificate_pin;
+ }
+
+ private JSONObject inputStreamToJson(InputStream input_stream) {
+ JSONObject json = null;
try {
- bytes = new byte[input_stream_file_contents.available()];
- if (input_stream_file_contents.read(bytes) > 0) {
- JSONObject file_contents = new JSONObject(new String(bytes));
- main_url = file_contents.getString(Provider.MAIN_URL);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (JSONException e) {
+ byte[] bytes = new byte[input_stream.available()];
+ if (input_stream.read(bytes) > 0)
+ json = new JSONObject(new String(bytes));
+ input_stream.reset();
+ } catch (IOException | JSONException e) {
e.printStackTrace();
}
- return main_url;
+ return json;
}
public Set<Provider> providers() {
Set<Provider> all_providers = new HashSet<Provider>();
all_providers.addAll(default_providers);
- all_providers.addAll(custom_providers);
+ if(custom_providers != null)
+ all_providers.addAll(custom_providers);
return all_providers;
}
@@ -124,25 +142,27 @@ public class ProviderManager implements AdapteeCollection<Provider> {
}
@Override
- public void add(Provider element) {
+ public boolean add(Provider element) {
if (!default_providers.contains(element))
- custom_providers.add(element);
+ return custom_providers.add(element);
+ else return true;
}
@Override
- public void remove(Provider element) {
- custom_providers.remove(element);
+ public boolean remove(Object element) {
+ return custom_providers.remove(element);
}
@Override
- public void addAll(Collection<Provider> elements) {
- custom_providers.addAll(elements);
+ public boolean addAll(Collection<? extends Provider> elements) {
+ return custom_providers.addAll(elements);
}
@Override
- public void removeAll(Collection<Provider> elements) {
- custom_providers.removeAll(elements);
- default_providers.removeAll(elements);
+ public boolean removeAll(Collection<?> elements) {
+ if(!elements.getClass().equals(Provider.class))
+ return false;
+ return default_providers.removeAll(elements) || custom_providers.removeAll(elements);
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java
deleted file mode 100644
index e43c8a25..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package se.leap.bitmaskclient;
-
-import android.os.*;
-
-import java.util.*;
-
-public class UserSessionStatus extends Observable {
- public static String TAG = UserSessionStatus.class.getSimpleName();
- private static UserSessionStatus current_status;
-
- public enum SessionStatus {
- LOGGED_IN,
- LOGGED_OUT,
- NOT_LOGGED_IN,
- DIDNT_LOG_OUT,
- LOGGING_IN,
- LOGGING_OUT,
- SIGNING_UP
- }
-
- private static SessionStatus session_status = SessionStatus.NOT_LOGGED_IN;
-
- public static UserSessionStatus getInstance() {
- if (current_status == null) {
- current_status = new UserSessionStatus();
- }
- return current_status;
- }
-
- private UserSessionStatus() {
- }
-
- private void sessionStatus(SessionStatus session_status) {
- this.session_status = session_status;
- }
-
- public SessionStatus sessionStatus() {
- return session_status;
- }
-
- public boolean inProgress() {
- return session_status == SessionStatus.LOGGING_IN
- || session_status == SessionStatus.LOGGING_OUT;
- }
-
- public static void updateStatus(SessionStatus session_status) {
- current_status = getInstance();
- current_status.sessionStatus(session_status);
- current_status.setChanged();
- current_status.notifyObservers();
- }
-
- @Override
- public String toString() {
- String username = User.userName();
-
- return username + " " + conjugateToBe(username) + " "
- + session_status.toString().toLowerCase().replaceAll("_", " ");
- }
-
- private String conjugateToBe(String subject) {
- String conjugation = "";
- if(subject.equalsIgnoreCase("I"))
- conjugation = "am";
- else if(subject.equalsIgnoreCase("you") || subject.equalsIgnoreCase("we")|| subject.equalsIgnoreCase("they"))
- conjugation = "are";
- else conjugation = "is";
-
- return conjugation;
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
index 02eedd77..2e3d7524 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
@@ -19,7 +19,6 @@ package se.leap.bitmaskclient;
import android.app.*;
import android.content.*;
import android.os.*;
-import android.util.*;
import android.view.*;
import android.widget.*;
@@ -29,35 +28,35 @@ import java.util.*;
import butterknife.*;
import de.blinkt.openvpn.activities.*;
+import mbanje.kurt.fabbutton.*;
import se.leap.bitmaskclient.eip.*;
-public class EipFragment extends Fragment implements Observer {
+public class VpnFragment extends Fragment implements Observer {
- public static String TAG = EipFragment.class.getSimpleName();
+ public static String TAG = VpnFragment.class.getSimpleName();
- protected static final String IS_PENDING = TAG + ".is_pending";
+ public static final String IS_PENDING = TAG + ".is_pending";
protected static final String IS_CONNECTED = TAG + ".is_connected";
- protected static final String STATUS_MESSAGE = TAG + ".status_message";
public static final String START_ON_BOOT = "start on boot";
- @InjectView(R.id.eipSwitch)
- Switch eip_switch;
- @InjectView(R.id.status_message)
- TextView status_message;
- @InjectView(R.id.eipProgress)
- ProgressBar progress_bar;
+ @InjectView(R.id.vpn_Status_Image)
+ FabButton vpn_status_image;
+ @InjectView(R.id.vpn_main_button)
+ Button main_button;
private static Dashboard dashboard;
- private static EIPReceiver mEIPReceiver;
+ private static EIPReceiver eip_receiver;
private static EipStatus eip_status;
- private boolean is_starting_to_connect;
private boolean wants_to_connect;
public void onAttach(Activity activity) {
super.onAttach(activity);
dashboard = (Dashboard) activity;
- dashboard.providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.DOWNLOAD_EIP_SERVICE);
+ ProviderAPIResultReceiver provider_api_receiver = new ProviderAPIResultReceiver(new Handler(), dashboard);
+
+ if(eip_receiver != null)
+ ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_EIP_SERVICE, provider_api_receiver);
}
@Override
@@ -65,7 +64,7 @@ public class EipFragment extends Fragment implements Observer {
super.onCreate(savedInstanceState);
eip_status = EipStatus.getInstance();
eip_status.addObserver(this);
- mEIPReceiver = new EIPReceiver(new Handler());
+ eip_receiver = new EIPReceiver(new Handler());
}
@Override
@@ -73,9 +72,6 @@ public class EipFragment extends Fragment implements Observer {
View view = inflater.inflate(R.layout.eip_service_fragment, container, false);
ButterKnife.inject(this, view);
- if (eip_status.isConnecting())
- eip_switch.setVisibility(View.VISIBLE);
-
Bundle arguments = getArguments();
if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT))
startEipFromScratch();
@@ -89,8 +85,6 @@ public class EipFragment extends Fragment implements Observer {
eip_status.setConnecting();
else if (savedInstanceState.getBoolean(IS_CONNECTED))
eip_status.setConnectedOrDisconnected();
- else
- status_message.setText(savedInstanceState.getString(STATUS_MESSAGE));
}
@Override
@@ -104,25 +98,20 @@ public class EipFragment extends Fragment implements Observer {
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(IS_PENDING, eip_status.isConnecting());
outState.putBoolean(IS_CONNECTED, eip_status.isConnected());
- outState.putString(STATUS_MESSAGE, status_message.getText().toString());
super.onSaveInstanceState(outState);
}
protected void saveStatus() {
- boolean is_on = eip_switch.isChecked();
+ boolean is_on = eip_status.isConnected() || eip_status.isConnecting();
Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit();
}
- void handleNewVpnCertificate() {
- handleSwitch(!eip_switch.isEnabled());
- }
-
- @OnCheckedChanged(R.id.eipSwitch)
- void handleSwitch(boolean isChecked) {
- if (isChecked)
- handleSwitchOn();
- else
+ @OnClick(R.id.vpn_main_button)
+ void handleIcon() {
+ if (eip_status.isConnected() || eip_status.isConnecting())
handleSwitchOff();
+ else
+ handleSwitchOn();
saveStatus();
}
@@ -156,23 +145,22 @@ public class EipFragment extends Fragment implements Observer {
} else if (eip_status.isConnected()) {
askToStopEIP();
} else
- setDisconnectedUI();
+ updateIcon();
}
private void askPendingStartCancellation() {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard);
alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title))
.setMessage(dashboard.getString(R.string.eip_cancel_connect_text))
- .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
askToStopEIP();
}
})
- .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() {
+ .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- eip_switch.setChecked(true);
}
})
.show();
@@ -180,15 +168,8 @@ public class EipFragment extends Fragment implements Observer {
public void startEipFromScratch() {
wants_to_connect = false;
- is_starting_to_connect = true;
- progress_bar.setVisibility(View.VISIBLE);
- eip_switch.setVisibility(View.VISIBLE);
- String status = dashboard.getString(R.string.eip_status_start_pending);
- status_message.setText(status);
-
- if (!eip_switch.isChecked()) {
- eip_switch.setChecked(true);
- }
+ eip_status.setConnecting();
+
saveStatus();
eipCommand(Constants.ACTION_START_EIP);
}
@@ -206,12 +187,6 @@ public class EipFragment extends Fragment implements Observer {
}
protected void stopEipIfPossible() {
-
- hideProgressBar();
-
- String message = dashboard.getString(R.string.eip_state_not_connected);
- status_message.setText(message);
-
eipCommand(Constants.ACTION_STOP_EIP);
}
@@ -219,16 +194,15 @@ public class EipFragment extends Fragment implements Observer {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard);
alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title))
.setMessage(dashboard.getString(R.string.eip_warning_browser_inconsistency))
- .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
stopEipIfPossible();
}
})
- .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() {
+ .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- eip_switch.setChecked(true);
}
})
.show();
@@ -248,7 +222,7 @@ public class EipFragment extends Fragment implements Observer {
// TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class);
vpn_intent.setAction(action);
- vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver);
+ vpn_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver);
dashboard.startService(vpn_intent);
}
@@ -267,71 +241,42 @@ public class EipFragment extends Fragment implements Observer {
}
private void handleNewState(EipStatus eip_status) {
- if (eip_status.wantsToDisconnect())
- setDisconnectedUI();
- else if (eip_status.isConnecting() || is_starting_to_connect)
- setInProgressUI(eip_status);
- else if (eip_status.isConnected())
- setConnectedUI();
- else if (eip_status.isDisconnected() && !eip_status.isConnecting())
- setDisconnectedUI();
- }
+ Context context = dashboard.getApplicationContext();
+ String error = eip_status.lastError(5, context);
- private void setConnectedUI() {
- hideProgressBar();
- adjustSwitch();
- is_starting_to_connect = false;
- status_message.setText(dashboard.getString(R.string.eip_state_connected));
- }
-
- private void setDisconnectedUI() {
- hideProgressBar();
- adjustSwitch();
- if (eip_status.errorInLast(5, dashboard.getApplicationContext())
- && !status_message.getText().toString().equalsIgnoreCase(dashboard.getString(R.string.eip_state_not_connected))) {
+ if (!error.isEmpty()) {
dashboard.showLog();
VoidVpnService.stop();
}
- status_message.setText(dashboard.getString(R.string.eip_state_not_connected));
- }
-
- private void adjustSwitch() {
- if (eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) {
- if (!eip_switch.isChecked()) {
- eip_switch.setChecked(true);
+ updateIcon();
+ updateButton();
+ }
+
+ private void updateIcon() {
+ if (eip_status.isConnected() || eip_status.isConnecting()) {
+ if(eip_status.isConnecting()) {
+ vpn_status_image.showProgress(true);
+ vpn_status_image.setIcon(R.drawable.ic_stat_vpn_empty_halo, R.drawable.ic_stat_vpn_empty_halo);
+ } else {
+ vpn_status_image.showProgress(false);
+ vpn_status_image.setIcon(R.drawable.ic_stat_vpn, R.drawable.ic_stat_vpn);
}
} else {
-
- if (eip_switch.isChecked()) {
- eip_switch.setChecked(false);
- }
+ vpn_status_image.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline);
+ vpn_status_image.showProgress(false);
}
}
- private void setInProgressUI(EipStatus eip_status) {
- int localizedResId = eip_status.getLocalizedResId();
- String logmessage = eip_status.getLogMessage();
- String prefix = dashboard.getString(localizedResId);
-
- showProgressBar();
- status_message.setText(prefix + " " + logmessage);
- is_starting_to_connect = false;
- adjustSwitch();
- }
-
- private void updatingCertificateUI() {
- showProgressBar();
- status_message.setText(getString(R.string.updating_certificate_message));
- }
-
- private void showProgressBar() {
- if (progress_bar != null)
- progress_bar.setVisibility(View.VISIBLE);
- }
-
- private void hideProgressBar() {
- if (progress_bar != null)
- progress_bar.setVisibility(View.GONE);
+ private void updateButton() {
+ if (eip_status.isConnected() || eip_status.isConnecting()) {
+ if(eip_status.isConnecting()) {
+ main_button.setText(dashboard.getString(android.R.string.cancel));
+ } else {
+ main_button.setText(dashboard.getString(R.string.vpn_button_turn_off));
+ }
+ } else {
+ main_button.setText(dashboard.getString(R.string.vpn_button_turn_on));
+ }
}
protected class EIPReceiver extends ResultReceiver {
@@ -374,7 +319,6 @@ public class EipFragment extends Fragment implements Observer {
case Activity.RESULT_OK:
break;
case Activity.RESULT_CANCELED:
- updatingCertificateUI();
dashboard.downloadVpnCertificate();
break;
}
@@ -394,6 +338,6 @@ public class EipFragment extends Fragment implements Observer {
public static EIPReceiver getReceiver() {
- return mEIPReceiver;
+ return eip_receiver;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
index beed7948..9ff7f1af 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -96,7 +96,7 @@ public final class EIP extends IntentService {
gateway = gateways_manager.select();
if (gateway != null && gateway.getProfile() != null) {
- mReceiver = EipFragment.getReceiver();
+ mReceiver = VpnFragment.getReceiver();
launchActiveGateway();
tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK);
} else
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index ad68f96e..4bfef1cb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -27,8 +27,11 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
private static EipStatus current_status;
private static VpnStatus.ConnectionStatus level = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
- private static boolean wants_to_disconnect = false;
+ private static boolean
+ wants_to_disconnect = false,
+ is_connecting = false;
+ int last_error_line = 0;
private String state, log_message;
private int localized_res_id;
@@ -46,9 +49,9 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
@Override
public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) {
updateStatus(state, logmessage, localizedResId, level);
- if (isConnected() || isDisconnected()) {
+ if (isConnected() || isDisconnected() || wantsToDisconnect()) {
setConnectedOrDisconnected();
- } else if (isConnecting())
+ } else
setConnecting();
}
@@ -66,10 +69,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public boolean isConnecting() {
- return
- !isConnected() &&
- !isDisconnected() &&
- !isPaused();
+ return is_connecting;
}
public boolean isConnected() {
@@ -85,19 +85,23 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public void setConnecting() {
+ is_connecting = true;
+
wants_to_disconnect = false;
current_status.setChanged();
current_status.notifyObservers();
}
public void setConnectedOrDisconnected() {
+ is_connecting = false;
wants_to_disconnect = false;
current_status.setChanged();
current_status.notifyObservers();
}
public void setDisconnecting() {
- wants_to_disconnect = false;
+ wants_to_disconnect = true;
+ is_connecting = false;
}
public String getState() {
@@ -133,18 +137,30 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public boolean errorInLast(int lines, Context context) {
- boolean result = false;
+ return !lastError(lines, context).isEmpty();
+ }
+
+ public String lastError(int lines, Context context) {
+ String error = "";
+
String[] error_keywords = {"error", "ERROR", "fatal", "FATAL"};
VpnStatus.LogItem[] log = VpnStatus.getlogbuffer();
+ if(log.length < last_error_line)
+ last_error_line = 0;
String message = "";
for (int i = 1; i <= lines && log.length > i; i++) {
- message = log[log.length - i].getString(context);
+ int line = log.length - i;
+ VpnStatus.LogItem log_item = log[line];
+ message = log_item.getString(context);
for (int j = 0; j < error_keywords.length; j++)
- if (message.contains(error_keywords[j]))
- result = true;
+ if (message.contains(error_keywords[j]) && line > last_error_line) {
+ error = message;
+ last_error_line = line;
+ }
}
- return result;
+
+ return error;
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
index 1c64328e..f41049c5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -16,19 +16,27 @@
*/
package se.leap.bitmaskclient.eip;
-import android.content.*;
+import android.content.Context;
+import android.content.SharedPreferences;
-import com.google.gson.*;
-import com.google.gson.reflect.*;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
-import org.json.*;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
-import de.blinkt.openvpn.*;
-import de.blinkt.openvpn.core.*;
-import se.leap.bitmaskclient.*;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.Connection;
+import de.blinkt.openvpn.core.ProfileManager;
+import se.leap.bitmaskclient.Provider;
/**
* @author parmegv
@@ -65,7 +73,7 @@ public class GatewaysManager {
}
public void addFromString(String gateways) {
- List<Gateway> gateways_list = new ArrayList<Gateway>();
+ List<Gateway> gateways_list = new ArrayList<>();
try {
gateways_list = new Gson().fromJson(gateways, list_type);
} catch (JsonSyntaxException e) {
@@ -75,7 +83,6 @@ public class GatewaysManager {
if (gateways_list != null) {
for (Gateway gateway : gateways_list)
addGateway(gateway);
- this.gateways.addAll(gateways_list);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
index dac92fe2..cbf0fed2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -50,6 +50,10 @@ public class VoidVpnService extends VpnService {
closeFd();
}
+ public static boolean isRunning() throws NullPointerException {
+ return thread.isAlive() && fd != null;
+ }
+
private static void closeFd() {
try {
if (fd != null)
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java
new file mode 100644
index 00000000..d1c56dee
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java
@@ -0,0 +1,28 @@
+package se.leap.bitmaskclient.userstatus;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import mbanje.kurt.fabbutton.CircleImageView;
+import se.leap.bitmaskclient.R;
+
+public class FabButton extends mbanje.kurt.fabbutton.FabButton {
+
+
+ public FabButton(Context context) {
+ super(context);
+ }
+
+ public FabButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FabButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ private CircleImageView getImage() {
+ return (CircleImageView) findViewById(R.id.fabbutton_circle);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
index e92c6b7b..7dbbe059 100644
--- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
@@ -14,7 +14,7 @@
* 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.userstatus;
import android.app.*;
import android.content.*;
@@ -23,6 +23,9 @@ import android.view.*;
import android.widget.*;
import butterknife.*;
+import se.leap.bitmaskclient.VpnFragment;
+import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.R;
/**
* Implements the log in dialog, currently without progress dialog.
@@ -56,8 +59,18 @@ public class SessionDialog extends DialogFragment {
private static boolean is_eip_pending = false;
- public SessionDialog() {
- setArguments(Bundle.EMPTY);
+ public static SessionDialog getInstance(Provider provider, Bundle arguments) {
+ SessionDialog dialog = new SessionDialog();
+ if (provider.getName().equalsIgnoreCase("riseup")) {
+ arguments =
+ arguments == Bundle.EMPTY ?
+ new Bundle() : arguments;
+ arguments.putBoolean(SessionDialog.ERRORS.RISEUP_WARNING.toString(), true);
+ }
+ if (arguments != null && !arguments.isEmpty()) {
+ dialog.setArguments(arguments);
+ }
+ return dialog;
}
public AlertDialog onCreateDialog(Bundle savedInstanceState) {
@@ -68,7 +81,7 @@ public class SessionDialog extends DialogFragment {
ButterKnife.inject(this, view);
Bundle arguments = getArguments();
- if (arguments != Bundle.EMPTY) {
+ if (arguments != Bundle.EMPTY && arguments != null) {
setUp(arguments);
}
@@ -100,7 +113,7 @@ public class SessionDialog extends DialogFragment {
}
private void setUp(Bundle arguments) {
- is_eip_pending = arguments.getBoolean(EipFragment.IS_PENDING, false);
+ is_eip_pending = arguments.getBoolean(VpnFragment.IS_PENDING, false);
if (arguments.containsKey(ERRORS.PASSWORD_INVALID_LENGTH.toString()))
password_field.setError(getString(R.string.error_not_valid_password_user_message));
else if (arguments.containsKey(ERRORS.RISEUP_WARNING.toString())) {
@@ -114,9 +127,10 @@ public class SessionDialog extends DialogFragment {
if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) {
username_field.setError(getString(R.string.username_ask));
}
- if (arguments.containsKey(getString(R.string.user_message)))
+ if (arguments.containsKey(getString(R.string.user_message))) {
user_message.setText(arguments.getString(getString(R.string.user_message)));
- else if (user_message.getVisibility() != TextView.VISIBLE)
+ user_message.setVisibility(View.VISIBLE);
+ } else if (user_message.getVisibility() != TextView.VISIBLE)
user_message.setVisibility(View.GONE);
if (!username_field.getText().toString().isEmpty() && password_field.isFocusable())
@@ -151,8 +165,9 @@ public class SessionDialog extends DialogFragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
+
try {
- interface_with_Dashboard = (SessionDialogInterface) activity;
+ interface_with_Dashboard = (SessionDialogInterface) activity.getFragmentManager().findFragmentById(R.id.user_status_fragment);;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement LogInDialogListener");
diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java
index 4bbd9a91..64ce0629 100644
--- a/app/src/main/java/se/leap/bitmaskclient/User.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java
@@ -14,15 +14,18 @@
* 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.userstatus;
+
+import se.leap.bitmaskclient.LeapSRPSession;
public class User {
- private static String user_name = "You";
+ private static String user_name;
private static User user;
- public static User getInstance() {
+ public static User init(String default_username) {
if (user == null) {
user = new User();
+ user.setUserName(default_username);
}
return user;
}
@@ -31,8 +34,7 @@ public class User {
User.user_name = user_name;
}
- private User() {
- }
+ private User() { }
public static String userName() {
return user_name;
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java
new file mode 100644
index 00000000..90ad0ffd
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient.userstatus;
+
+import android.content.res.*;
+
+import java.util.*;
+
+import se.leap.bitmaskclient.R;
+
+public class UserStatus extends Observable {
+ public static String TAG = UserStatus.class.getSimpleName();
+ private static UserStatus current_status;
+ private static Resources resources;
+
+ public enum SessionStatus {
+ LOGGED_IN,
+ LOGGED_OUT,
+ NOT_LOGGED_IN,
+ DIDNT_LOG_OUT,
+ LOGGING_IN,
+ LOGGING_OUT,
+ SIGNING_UP;
+
+ @Override
+ public String toString() {
+ int id = 0;
+ if(this == SessionStatus.LOGGED_IN)
+ id = R.string.logged_in_user_status;
+ else if(this == SessionStatus.LOGGED_OUT)
+ id = R.string.logged_out_user_status;
+ else if(this == SessionStatus.NOT_LOGGED_IN)
+ id = R.string.not_logged_in_user_status;
+ else if(this == SessionStatus.DIDNT_LOG_OUT)
+ id = R.string.didnt_log_out_user_status;
+ else if(this == SessionStatus.LOGGING_IN)
+ id = R.string.logging_in_user_status;
+ else if(this == SessionStatus.LOGGING_OUT)
+ id = R.string.logging_out_user_status;
+ else if(this == SessionStatus.SIGNING_UP)
+ id = R.string.signingup_message;
+
+ return resources.getString(id);
+ }
+ }
+
+ private static SessionStatus session_status = SessionStatus.LOGGED_OUT;
+
+ public static UserStatus getInstance(Resources resources) {
+ if (current_status == null) {
+ current_status = new UserStatus(resources);
+ }
+ return current_status;
+ }
+
+ private UserStatus(Resources resources) {
+ UserStatus.resources = resources;
+ }
+
+ private void sessionStatus(SessionStatus session_status) {
+ this.session_status = session_status;
+ }
+
+ public SessionStatus sessionStatus() {
+ return session_status;
+ }
+
+ public boolean inProgress() {
+ return session_status == SessionStatus.LOGGING_IN
+ || session_status == SessionStatus.LOGGING_OUT;
+ }
+
+ public boolean isLoggedIn() {
+ return session_status == SessionStatus.LOGGED_IN;
+ }
+
+ public boolean isLoggedOut() {
+ return session_status == SessionStatus.LOGGED_OUT;
+ }
+
+ public boolean notLoggedIn() {
+ return session_status == SessionStatus.NOT_LOGGED_IN;
+ }
+
+ public boolean didntLogOut() {
+ return session_status == SessionStatus.DIDNT_LOG_OUT;
+ }
+
+ public static void updateStatus(SessionStatus session_status, Resources resources) {
+ current_status = getInstance(resources);
+ current_status.sessionStatus(session_status);
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
+
+ @Override
+ public String toString() {
+ String user_session_status = User.userName();
+
+ String default_username = resources.getString(R.string.default_username, "");
+ if(user_session_status.isEmpty() && !default_username.equalsIgnoreCase("null")) user_session_status = default_username;
+ user_session_status += " " + session_status.toString();
+
+ user_session_status = user_session_status.trim();
+ if(User.userName().isEmpty())
+ user_session_status = capitalize(user_session_status);
+ return user_session_status;
+ }
+
+ private String capitalize(String to_be_capitalized) {
+ return to_be_capitalized.substring(0,1).toUpperCase() + to_be_capitalized.substring(1);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
new file mode 100644
index 00000000..20189904
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
@@ -0,0 +1,181 @@
+package se.leap.bitmaskclient.userstatus;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnClick;
+import se.leap.bitmaskclient.Dashboard;
+import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.ProviderAPI;
+import se.leap.bitmaskclient.ProviderAPICommand;
+import se.leap.bitmaskclient.ProviderAPIResultReceiver;
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.eip.EipStatus;
+
+public class UserStatusFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface {
+
+ public static String TAG = UserStatusFragment.class.getSimpleName();
+ private static Dashboard dashboard;
+ private ProviderAPIResultReceiver providerAPI_result_receiver;
+
+ @InjectView(R.id.user_status_username)
+ TextView username;
+ @InjectView(R.id.user_status_icon)
+ FabButton icon;
+ @InjectView(R.id.user_status_button)
+ Button button;
+
+ private UserStatus status;
+ private boolean allows_registration = false;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ status = UserStatus.getInstance(getResources());
+ status.addObserver(this);
+ }
+
+ @Override
+ public void onSaveInstanceState(@NotNull Bundle outState) {
+ if (username != null && username.getVisibility() == TextView.VISIBLE)
+ outState.putSerializable(UserStatus.TAG, status.sessionStatus());
+
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View view = inflater.inflate(R.layout.user_session_fragment, container, false);
+ ButterKnife.inject(this, view);
+
+ Bundle arguments = getArguments();
+ allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION);
+ handleNewStatus(status);
+
+ return view;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ dashboard = (Dashboard) activity;
+
+ providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), dashboard);
+ }
+
+ public void restoreSessionStatus(Bundle savedInstanceState) {
+ if (savedInstanceState != null)
+ if (savedInstanceState.containsKey(UserStatus.TAG)) {
+ UserStatus.SessionStatus status = (UserStatus.SessionStatus) savedInstanceState.getSerializable(UserStatus.TAG);
+ this.status.updateStatus(status, getResources());
+ }
+ }
+
+ @OnClick(R.id.user_status_button)
+ public void handleButton() {
+ android.util.Log.d(TAG, status.toString());
+ if(status.isLoggedIn())
+ logOut();
+ else if(status.isLoggedOut())
+ dashboard.sessionDialog(Bundle.EMPTY);
+ else if(status.inProgress())
+ cancelLoginOrSignup();
+ }
+
+ @Override
+ public void update(Observable observable, Object data) {
+ if (observable instanceof UserStatus) {
+ final UserStatus status = (UserStatus) observable;
+ dashboard.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ handleNewStatus(status);
+ }
+ });
+ }
+ }
+
+ private void handleNewStatus(UserStatus status) {
+ this.status = status;
+ if (allows_registration) {
+ if (this.status.inProgress())
+ showUserSessionProgressBar();
+ else
+ hideUserSessionProgressBar();
+ changeMessage();
+ updateButton();
+ }
+ }
+
+ private void showUserSessionProgressBar() {
+ icon.showProgress(true);
+ }
+
+ private void hideUserSessionProgressBar() {
+ icon.showProgress(false);
+ }
+
+ private void changeMessage() {
+ final String message = User.userName();
+ username.setText(message);
+ }
+
+ private void updateButton() {
+ if(status.isLoggedIn() || status.didntLogOut())
+ button.setText(dashboard.getString(R.string.logout_button));
+ else if(allows_registration) {
+ if (status.isLoggedOut() || status.notLoggedIn())
+ button.setText(dashboard.getString(R.string.login_button));
+ else if (status.inProgress())
+ button.setText(dashboard.getString(android.R.string.cancel));
+ }
+ }
+
+
+ @Override
+ public void signUp(String username, String password) {
+ User.setUserName(username);
+ Bundle parameters = bundlePassword(password);
+ ProviderAPICommand.execute(parameters, ProviderAPI.SIGN_UP, providerAPI_result_receiver);
+ }
+
+ @Override
+ public void logIn(String username, String password) {
+ User.setUserName(username);
+ Bundle parameters = bundlePassword(password);
+ ProviderAPICommand.execute(parameters, ProviderAPI.LOG_IN, providerAPI_result_receiver);
+ }
+
+ public void logOut() {
+ android.util.Log.d(TAG, "Log out");
+ ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.LOG_OUT, providerAPI_result_receiver);
+ }
+
+ public void cancelLoginOrSignup() {
+ EipStatus.getInstance().setConnectedOrDisconnected();
+ }
+
+ private Bundle bundlePassword(String password) {
+ Bundle parameters = new Bundle();
+ if (!password.isEmpty())
+ parameters.putString(SessionDialog.PASSWORD, password);
+ return parameters;
+ }
+}