From c8d84fb5fdf1bc834c3ef26eacb4eb1df9ed3668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 7 Apr 2015 17:45:20 +0200 Subject: Trying to conjugate the Spanish verbs programmatically. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 5 ++-- .../java/se/leap/bitmaskclient/LeapSRPSession.java | 1 - app/src/main/java/se/leap/bitmaskclient/User.java | 12 ++++++---- .../se/leap/bitmaskclient/UserSessionStatus.java | 27 +++++++++++++--------- 4 files changed, 27 insertions(+), 18 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index ee64a1b3..4207872d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -78,7 +78,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn super.onCreate(savedInstanceState); app = this; - user_session_status = UserSessionStatus.getInstance(); + user_session_status = UserSessionStatus.getInstance(getResources()); user_session_status.addObserver(this); PRNGFixes.apply(); @@ -86,6 +86,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); + User.init(); restoreProvider(savedInstanceState); if (provider == null || provider.getName().isEmpty()) @@ -109,7 +110,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn if (savedInstanceState != null) if (savedInstanceState.containsKey(UserSessionStatus.TAG)) { UserSessionStatus.SessionStatus status = (UserSessionStatus.SessionStatus) savedInstanceState.getSerializable(UserSessionStatus.TAG); - user_session_status.updateStatus(status); + user_session_status.updateStatus(status, getResources()); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index b961350e..1ced6d60 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; diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/User.java index 4bbd9a91..5b0bab47 100644 --- a/app/src/main/java/se/leap/bitmaskclient/User.java +++ b/app/src/main/java/se/leap/bitmaskclient/User.java @@ -17,12 +17,15 @@ package se.leap.bitmaskclient; public class User { - private static String user_name = "You"; + private static String user_name; private static User user; + public static int DEFAULT_CONJUGATION_PERSON = 1; - public static User getInstance() { + public static User init() { if (user == null) { - user = new User(); + String[] personal_pronouns = Dashboard.getContext().getResources().getStringArray(R.array.personal_pronouns); + String default_username = personal_pronouns[DEFAULT_CONJUGATION_PERSON]; + user = new User(default_username); } return user; } @@ -31,7 +34,8 @@ public class User { User.user_name = user_name; } - private User() { + private User(String user_name) { + User.user_name = user_name; } public static String userName() { diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java index e43c8a25..ee818635 100644 --- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java @@ -16,13 +16,14 @@ */ package se.leap.bitmaskclient; -import android.os.*; +import android.content.res.*; import java.util.*; public class UserSessionStatus extends Observable { public static String TAG = UserSessionStatus.class.getSimpleName(); private static UserSessionStatus current_status; + private static Resources resources; public enum SessionStatus { LOGGED_IN, @@ -36,14 +37,15 @@ public class UserSessionStatus extends Observable { private static SessionStatus session_status = SessionStatus.NOT_LOGGED_IN; - public static UserSessionStatus getInstance() { + public static UserSessionStatus getInstance(Resources resources) { if (current_status == null) { - current_status = new UserSessionStatus(); + current_status = new UserSessionStatus(resources); } return current_status; } - private UserSessionStatus() { + private UserSessionStatus(Resources resources) { + UserSessionStatus.resources = resources; } private void sessionStatus(SessionStatus session_status) { @@ -59,8 +61,8 @@ public class UserSessionStatus extends Observable { || session_status == SessionStatus.LOGGING_OUT; } - public static void updateStatus(SessionStatus session_status) { - current_status = getInstance(); + public static void updateStatus(SessionStatus session_status, Resources resources) { + current_status = getInstance(resources); current_status.sessionStatus(session_status); current_status.setChanged(); current_status.notifyObservers(); @@ -76,11 +78,14 @@ public class UserSessionStatus extends Observable { 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"; + String[] personal_pronouns = resources.getStringArray(R.array.personal_pronouns); + String[] verb_to_be = resources.getStringArray(R.array.verb_to_be); + for (int i = 0; i < personal_pronouns.length ; i++) + if(subject.equalsIgnoreCase(personal_pronouns[i])) { + conjugation = verb_to_be[i]; + break; + } + if(conjugation.isEmpty()) conjugation = verb_to_be[User.DEFAULT_CONJUGATION_PERSON]; return conjugation; } -- cgit v1.2.3 From f8f636d90a1110554eda858420e5052e88a250b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 10 Apr 2015 10:39:51 +0200 Subject: Seems to work. --- app/src/main/java/se/leap/bitmaskclient/User.java | 10 ++---- .../se/leap/bitmaskclient/UserSessionStatus.java | 37 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 11 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/User.java index 5b0bab47..f3d3b8b1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/User.java +++ b/app/src/main/java/se/leap/bitmaskclient/User.java @@ -17,15 +17,13 @@ package se.leap.bitmaskclient; public class User { - private static String user_name; + private static String user_name = ""; private static User user; public static int DEFAULT_CONJUGATION_PERSON = 1; public static User init() { if (user == null) { - String[] personal_pronouns = Dashboard.getContext().getResources().getStringArray(R.array.personal_pronouns); - String default_username = personal_pronouns[DEFAULT_CONJUGATION_PERSON]; - user = new User(default_username); + user = new User(); } return user; } @@ -34,9 +32,7 @@ public class User { User.user_name = user_name; } - private User(String user_name) { - User.user_name = user_name; - } + private User() { } public static String userName() { return user_name; diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java index ee818635..d5d53b6f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java @@ -32,7 +32,26 @@ public class UserSessionStatus extends Observable { DIDNT_LOG_OUT, LOGGING_IN, LOGGING_OUT, - SIGNING_UP + 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; + + return resources.getString(id); + } } private static SessionStatus session_status = SessionStatus.NOT_LOGGED_IN; @@ -70,10 +89,20 @@ public class UserSessionStatus extends Observable { @Override public String toString() { - String username = User.userName(); + String user_session_status = User.userName(); + + String default_username = resources.getString(R.string.default_user, ""); + 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; + } - return username + " " + conjugateToBe(username) + " " - + session_status.toString().toLowerCase().replaceAll("_", " "); + private String capitalize(String to_be_capitalized) { + return to_be_capitalized.substring(0,1).toUpperCase() + to_be_capitalized.substring(1); } private String conjugateToBe(String subject) { -- cgit v1.2.3 From a1a00e4340ac869eb6be524fb9ae1197ab79762c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 14 Apr 2015 17:57:54 +0200 Subject: Signing up string. --- app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java index d5d53b6f..a767ec97 100644 --- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java @@ -49,6 +49,8 @@ public class UserSessionStatus extends Observable { 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); } -- cgit v1.2.3 From 2073ced5c853a8919f4d1c86b2d7a2cec6659c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 14 Apr 2015 18:30:27 +0200 Subject: Show session error in user dialog --- app/src/main/java/se/leap/bitmaskclient/SessionDialog.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java index e92c6b7b..30344ff2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java @@ -114,9 +114,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()) -- cgit v1.2.3 From c8994b645b607723bdaba4c2aa1ff0d19a9c0c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 15 Apr 2015 10:41:59 +0200 Subject: Set accept-language in ProviderAPI, language-country String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry(); --- .../main/java/se/leap/bitmaskclient/UserSessionStatus.java | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java index a767ec97..28c7ecc7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java @@ -106,18 +106,4 @@ public class UserSessionStatus extends Observable { private String capitalize(String to_be_capitalized) { return to_be_capitalized.substring(0,1).toUpperCase() + to_be_capitalized.substring(1); } - - private String conjugateToBe(String subject) { - String conjugation = ""; - String[] personal_pronouns = resources.getStringArray(R.array.personal_pronouns); - String[] verb_to_be = resources.getStringArray(R.array.verb_to_be); - for (int i = 0; i < personal_pronouns.length ; i++) - if(subject.equalsIgnoreCase(personal_pronouns[i])) { - conjugation = verb_to_be[i]; - break; - } - if(conjugation.isEmpty()) conjugation = verb_to_be[User.DEFAULT_CONJUGATION_PERSON]; - - return conjugation; - } } -- cgit v1.2.3 From 106502134068155563f877966e1c5b0edfae2d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 15 Apr 2015 13:01:10 +0200 Subject: Wants to disconnect and is connecting work fine. --- .../main/java/se/leap/bitmaskclient/EipFragment.java | 9 +++------ .../java/se/leap/bitmaskclient/eip/EipStatus.java | 20 ++++++++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 02eedd77..bfa67815 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -50,7 +50,6 @@ public class EipFragment extends Fragment implements Observer { private static Dashboard dashboard; private static EIPReceiver mEIPReceiver; private static EipStatus eip_status; - private boolean is_starting_to_connect; private boolean wants_to_connect; public void onAttach(Activity activity) { @@ -180,7 +179,7 @@ public class EipFragment extends Fragment implements Observer { public void startEipFromScratch() { wants_to_connect = false; - is_starting_to_connect = true; + eip_status.setConnecting(); progress_bar.setVisibility(View.VISIBLE); eip_switch.setVisibility(View.VISIBLE); String status = dashboard.getString(R.string.eip_status_start_pending); @@ -269,7 +268,7 @@ 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) + else if (eip_status.isConnecting()) setInProgressUI(eip_status); else if (eip_status.isConnected()) setConnectedUI(); @@ -280,7 +279,6 @@ public class EipFragment extends Fragment implements Observer { private void setConnectedUI() { hideProgressBar(); adjustSwitch(); - is_starting_to_connect = false; status_message.setText(dashboard.getString(R.string.eip_state_connected)); } @@ -296,7 +294,7 @@ public class EipFragment extends Fragment implements Observer { } private void adjustSwitch() { - if (eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) { + if (eip_status.isConnected() || eip_status.isConnecting()) { if (!eip_switch.isChecked()) { eip_switch.setChecked(true); } @@ -315,7 +313,6 @@ public class EipFragment extends Fragment implements Observer { showProgressBar(); status_message.setText(prefix + " " + logmessage); - is_starting_to_connect = false; adjustSwitch(); } 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..b7f95277 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -27,7 +27,10 @@ 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; + 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() { -- cgit v1.2.3 From e2b289726f3c1813f9fafecc94bc61a70dbdb899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 21 Apr 2015 20:37:19 +0200 Subject: Pinning connection to provider.json Using AndroidPinning library from Moxie, I make sure the provider.json file Bitmask downloads is fetched from a pinned https connection, so that the api certificate fingerprint is the good one. --- .../main/java/se/leap/bitmaskclient/Provider.java | 14 +++--- .../se/leap/bitmaskclient/ProviderManager.java | 52 ++++++++++++++-------- 2 files changed, 42 insertions(+), 24 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index ee06a586..54bfcc19 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -32,6 +32,7 @@ public final class Provider implements Parcelable { private JSONObject definition; // Represents our Provider's provider.json private URL main_url; + private String certificate_pin; final public static String API_URL = "api_uri", @@ -62,8 +63,9 @@ public final class Provider implements Parcelable { this.main_url = main_url; } - public Provider(File provider_file) { - + public Provider(URL main_url, String certificate_pin) { + this.main_url = main_url; + this.certificate_pin = certificate_pin; } public static final Parcelable.Creator CREATOR @@ -81,11 +83,9 @@ public final class Provider implements Parcelable { try { main_url = 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(); } } @@ -106,6 +106,8 @@ public final class Provider implements Parcelable { return main_url; } + protected String certificatePin() { return certificate_pin; } + protected String getName() { // Should we pass the locale in, or query the system here? String lang = Locale.getDefault().getLanguage(); diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index 40fe8b5a..220a71c8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -49,11 +49,14 @@ public class ProviderManager implements AdapteeCollection { Set providers = new HashSet(); 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,30 +78,43 @@ public class ProviderManager implements AdapteeCollection { 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 providers() { -- cgit v1.2.3 From 7d6d55cb62fcdc1e3a36f2634f0399b2d77db263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 22 Apr 2015 12:29:04 +0200 Subject: Initialize ca fingerprint, avoiding nullpointer Danger on defaults to true in debug build --- app/src/main/java/se/leap/bitmaskclient/Provider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 54bfcc19..a030927d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -32,7 +32,7 @@ public final class Provider implements Parcelable { private JSONObject definition; // Represents our Provider's provider.json private URL main_url; - private String certificate_pin; + private String certificate_pin = ""; final public static String API_URL = "api_uri", -- cgit v1.2.3 From cdeaf6c2ae2fa96a2ef1e0ae6c931c6d50b27271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 16 Apr 2015 13:02:06 +0200 Subject: Button with circle progress, added. Next step: a bit of UI design, removing the switch. --- .../java/se/leap/bitmaskclient/EipFragment.java | 24 ++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index bfa67815..454530be 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.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,6 +28,7 @@ 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 { @@ -46,6 +46,8 @@ public class EipFragment extends Fragment implements Observer { TextView status_message; @InjectView(R.id.eipProgress) ProgressBar progress_bar; + @InjectView(R.id.vpn_Status_Image) + FabButton vpn_status_image; private static Dashboard dashboard; private static EIPReceiver mEIPReceiver; @@ -112,6 +114,16 @@ public class EipFragment extends Fragment implements Observer { Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); } + @OnClick(R.id.vpn_Status_Image) + void handleIcon() { + if (eip_status.isConnected() || eip_status.isConnecting()) + handleSwitchOff(); + else + handleSwitchOn(); + + saveStatus(); + } + void handleNewVpnCertificate() { handleSwitch(!eip_switch.isEnabled()); } @@ -298,11 +310,19 @@ public class EipFragment extends Fragment implements Observer { if (!eip_switch.isChecked()) { eip_switch.setChecked(true); } + 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); } } -- cgit v1.2.3 From 90c28f492b800b706c1d6f14482baf3e75c4be7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 16 Apr 2015 13:16:04 +0200 Subject: Remove eip switch. --- .../java/se/leap/bitmaskclient/EipFragment.java | 31 ++-------------------- 1 file changed, 2 insertions(+), 29 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 454530be..a9ceec52 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -40,8 +40,6 @@ public class EipFragment extends Fragment implements Observer { 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) @@ -74,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(); @@ -110,7 +105,7 @@ public class EipFragment extends Fragment implements Observer { } 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(); } @@ -125,17 +120,7 @@ public class EipFragment extends Fragment implements Observer { } void handleNewVpnCertificate() { - handleSwitch(!eip_switch.isEnabled()); - } - - @OnCheckedChanged(R.id.eipSwitch) - void handleSwitch(boolean isChecked) { - if (isChecked) - handleSwitchOn(); - else - handleSwitchOff(); - - saveStatus(); + handleIcon(); } private void handleSwitchOn() { @@ -183,7 +168,6 @@ public class EipFragment extends Fragment implements Observer { .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - eip_switch.setChecked(true); } }) .show(); @@ -193,13 +177,9 @@ public class EipFragment extends Fragment implements Observer { wants_to_connect = false; eip_status.setConnecting(); 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); - } saveStatus(); eipCommand(Constants.ACTION_START_EIP); } @@ -239,7 +219,6 @@ public class EipFragment extends Fragment implements Observer { .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - eip_switch.setChecked(true); } }) .show(); @@ -307,9 +286,6 @@ public class EipFragment extends Fragment implements Observer { private void adjustSwitch() { if (eip_status.isConnected() || eip_status.isConnecting()) { - if (!eip_switch.isChecked()) { - eip_switch.setChecked(true); - } 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); @@ -318,9 +294,6 @@ public class EipFragment extends Fragment implements Observer { 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); } -- cgit v1.2.3 From 8862197a0a138f942e9c76a29aaf189f4c5141b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 16 Apr 2015 13:20:45 +0200 Subject: Remove progress bar. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 1 - .../main/java/se/leap/bitmaskclient/EipFragment.java | 20 -------------------- 2 files changed, 21 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 4207872d..d5d06322 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -373,7 +373,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn 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); } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index a9ceec52..bed61d24 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -42,8 +42,6 @@ public class EipFragment extends Fragment implements Observer { @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; @@ -176,7 +174,6 @@ public class EipFragment extends Fragment implements Observer { public void startEipFromScratch() { wants_to_connect = false; eip_status.setConnecting(); - progress_bar.setVisibility(View.VISIBLE); String status = dashboard.getString(R.string.eip_status_start_pending); status_message.setText(status); @@ -197,9 +194,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); @@ -268,13 +262,11 @@ public class EipFragment extends Fragment implements Observer { } private void setConnectedUI() { - hideProgressBar(); adjustSwitch(); 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))) { @@ -304,26 +296,14 @@ public class EipFragment extends Fragment implements Observer { String logmessage = eip_status.getLogMessage(); String prefix = dashboard.getString(localizedResId); - showProgressBar(); status_message.setText(prefix + " " + logmessage); 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); - } - protected class EIPReceiver extends ResultReceiver { protected EIPReceiver(Handler handler) { -- cgit v1.2.3 From d486768d6b0664d9032605897c8f1847ef4e3a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 20 Apr 2015 18:20:05 +0200 Subject: Remove textual status. I had a difficult moment trying to detect if the LogWindow had already been shown after an error. Finally, I implemented a LogWindowWrapper which contains a field for the reason it was shown, so that we can check if the previous error is the same than the current one leading to the avoidance of the second LogWindow. For this to work, we need to reset that reason each time we trigger a new vpn state (i.e. each time the user taps on the vpn icon). --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 13 +------ .../java/se/leap/bitmaskclient/EipFragment.java | 45 ++++++---------------- .../se/leap/bitmaskclient/LogWindowWrapper.java | 41 ++++++++++++++++++++ .../java/se/leap/bitmaskclient/eip/EipStatus.java | 15 ++++++-- .../se/leap/bitmaskclient/eip/VoidVpnService.java | 4 ++ 5 files changed, 70 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index d5d06322..921bf95b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -285,8 +285,8 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } public void showLog() { - Intent startLW = new Intent(getContext(), LogWindow.class); - startActivity(startLW); + LogWindowWrapper log_window_wrapper = LogWindowWrapper.getInstance(getContext()); + log_window_wrapper.showLog(); } @Override @@ -372,10 +372,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } protected void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) { - if (eip_fragment != null && progressbar_message_resId != 0) { - setStatusMessage(progressbar_message_resId); - } - Intent command = prepareProviderAPICommand(parameters, providerApi_action); startService(command); } @@ -449,11 +445,6 @@ 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; } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index bed61d24..c92ae3cd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -20,7 +20,6 @@ import android.app.*; import android.content.*; import android.os.*; import android.view.*; -import android.widget.*; import org.jetbrains.annotations.*; @@ -37,11 +36,9 @@ public class EipFragment extends Fragment implements Observer { protected 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"; + private static final String SHOWED_LOG = TAG + ".showed_log"; - @InjectView(R.id.status_message) - TextView status_message; @InjectView(R.id.vpn_Status_Image) FabButton vpn_status_image; @@ -83,8 +80,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 @@ -98,7 +93,6 @@ 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); } @@ -109,6 +103,7 @@ public class EipFragment extends Fragment implements Observer { @OnClick(R.id.vpn_Status_Image) void handleIcon() { + LogWindowWrapper.getInstance(dashboard.getApplicationContext()).clearReason(); if (eip_status.isConnected() || eip_status.isConnecting()) handleSwitchOff(); else @@ -174,8 +169,6 @@ public class EipFragment extends Fragment implements Observer { public void startEipFromScratch() { wants_to_connect = false; eip_status.setConnecting(); - String status = dashboard.getString(R.string.eip_status_start_pending); - status_message.setText(status); saveStatus(); eipCommand(Constants.ACTION_START_EIP); @@ -194,9 +187,6 @@ public class EipFragment extends Fragment implements Observer { } protected void stopEipIfPossible() { - String message = dashboard.getString(R.string.eip_state_not_connected); - status_message.setText(message); - eipCommand(Constants.ACTION_STOP_EIP); } @@ -251,29 +241,24 @@ public class EipFragment extends Fragment implements Observer { } private void handleNewState(EipStatus eip_status) { - if (eip_status.wantsToDisconnect()) - setDisconnectedUI(); - else if (eip_status.isConnecting()) - 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); + LogWindowWrapper log_window = LogWindowWrapper.getInstance(context); + + if (!error.isEmpty() && log_window != null && !log_window.reason().equalsIgnoreCase(error)) { + log_window.showLog(); + log_window.showedBecauseOf(error); + VoidVpnService.stop(); + } + adjustSwitch(); } private void setConnectedUI() { adjustSwitch(); - status_message.setText(dashboard.getString(R.string.eip_state_connected)); } private void setDisconnectedUI() { adjustSwitch(); - if (eip_status.errorInLast(5, dashboard.getApplicationContext()) - && !status_message.getText().toString().equalsIgnoreCase(dashboard.getString(R.string.eip_state_not_connected))) { - dashboard.showLog(); - VoidVpnService.stop(); - } - status_message.setText(dashboard.getString(R.string.eip_state_not_connected)); } private void adjustSwitch() { @@ -292,16 +277,10 @@ public class EipFragment extends Fragment implements Observer { } private void setInProgressUI(EipStatus eip_status) { - int localizedResId = eip_status.getLocalizedResId(); - String logmessage = eip_status.getLogMessage(); - String prefix = dashboard.getString(localizedResId); - - status_message.setText(prefix + " " + logmessage); adjustSwitch(); } private void updatingCertificateUI() { - status_message.setText(getString(R.string.updating_certificate_message)); } protected class EIPReceiver extends ResultReceiver { 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..441eb28e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java @@ -0,0 +1,41 @@ +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; + private String reason = ""; + + 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; + } + + public void clearReason() { + reason = ""; + } + + public void showedBecauseOf(String reason) { + this.reason = reason; + } + + public String reason() { + return reason; + } +} 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 b7f95277..356cf6b0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -137,18 +137,25 @@ 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(); String message = ""; for (int i = 1; i <= lines && log.length > i; i++) { - message = log[log.length - i].getString(context); + VpnStatus.LogItem log_item = log[log.length - i]; + message = log_item.getString(context); for (int j = 0; j < error_keywords.length; j++) if (message.contains(error_keywords[j])) - result = true; + error = message; } - return result; + + return error; } @Override 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) -- cgit v1.2.3 From 0a7cb34e42fc3b8bf8623bda45cd4d76079a96c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 20 Apr 2015 19:55:00 +0200 Subject: Always show the log if an error happens. I've removed the "reason" management in LogWindowWrapper, letting EipStatus display the error log message only if it's a new one (based on the log buffer position). --- app/src/main/java/se/leap/bitmaskclient/EipFragment.java | 7 ++----- app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java | 11 ++++++++--- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index c92ae3cd..a13cab09 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -103,7 +103,6 @@ public class EipFragment extends Fragment implements Observer { @OnClick(R.id.vpn_Status_Image) void handleIcon() { - LogWindowWrapper.getInstance(dashboard.getApplicationContext()).clearReason(); if (eip_status.isConnected() || eip_status.isConnecting()) handleSwitchOff(); else @@ -243,11 +242,9 @@ public class EipFragment extends Fragment implements Observer { private void handleNewState(EipStatus eip_status) { Context context = dashboard.getApplicationContext(); String error = eip_status.lastError(5, context); - LogWindowWrapper log_window = LogWindowWrapper.getInstance(context); - if (!error.isEmpty() && log_window != null && !log_window.reason().equalsIgnoreCase(error)) { - log_window.showLog(); - log_window.showedBecauseOf(error); + if (!error.isEmpty()) { + dashboard.showLog(); VoidVpnService.stop(); } adjustSwitch(); 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 356cf6b0..4bfef1cb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -31,7 +31,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { wants_to_disconnect = false, is_connecting = false; - + int last_error_line = 0; private String state, log_message; private int localized_res_id; @@ -146,13 +146,18 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { 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++) { - VpnStatus.LogItem log_item = log[log.length - i]; + 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])) + if (message.contains(error_keywords[j]) && line > last_error_line) { error = message; + last_error_line = line; + } } return error; -- cgit v1.2.3 From 1a1b49a36e6c8ddccdb2a3308b6739601a691efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 20 Apr 2015 19:57:22 +0200 Subject: Remove traces of the "reason" field. --- .../main/java/se/leap/bitmaskclient/LogWindowWrapper.java | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java b/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java index 441eb28e..2476f6a4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java +++ b/app/src/main/java/se/leap/bitmaskclient/LogWindowWrapper.java @@ -9,7 +9,6 @@ public class LogWindowWrapper { private static String TAG = LogWindowWrapper.class.getName(); private Context context; - private String reason = ""; public LogWindowWrapper(Context context) { this.context = context; @@ -26,16 +25,4 @@ public class LogWindowWrapper { instance = new LogWindowWrapper(context); return instance; } - - public void clearReason() { - reason = ""; - } - - public void showedBecauseOf(String reason) { - this.reason = reason; - } - - public String reason() { - return reason; - } } -- cgit v1.2.3 From 449c3953ce79947554bbfd6ed0386d68aa9f04bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 22 Apr 2015 14:20:09 +0200 Subject: Avoid the check for a null provider. A provider can be asked if it's configured or not, so that we don't find more provider = null issues. I've created a DefaultedURL which links to https://example.net, so that we can initialize an URL. I use composition instead of inheritance, since URL class is final. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 13 ++++---- .../java/se/leap/bitmaskclient/DefaultedURL.java | 37 ++++++++++++++++++++++ .../main/java/se/leap/bitmaskclient/Provider.java | 33 ++++++++++++------- 3 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 921bf95b..ddd03dbc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -68,7 +68,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn ProgressBar user_session_status_progress_bar; EipFragment eip_fragment; - private Provider provider; + private Provider provider = new Provider(); private UserSessionStatus user_session_status; public ProviderAPIResultReceiver providerAPI_result_receiver; private boolean switching_provider; @@ -89,7 +89,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn User.init(); 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)); @@ -102,7 +102,7 @@ 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(); } @@ -116,8 +116,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn @Override protected void onSaveInstanceState(@NotNull Bundle outState) { - if (provider != null) - outState.putParcelable(Provider.KEY, provider); + 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()); @@ -125,9 +124,9 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } 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(); 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/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index a030927d..a66d53e7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -30,8 +30,8 @@ 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 @@ -59,12 +59,14 @@ 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(URL main_url, String certificate_pin) { - this.main_url = main_url; + this.main_url.setUrl(main_url); this.certificate_pin = certificate_pin; } @@ -81,7 +83,7 @@ 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.isEmpty()) definition = new JSONObject((definition_string)); @@ -90,6 +92,14 @@ public final class Provider implements Parcelable { } } + 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,10 +109,10 @@ 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; } @@ -118,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(".")); } } @@ -181,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()); } @@ -190,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; } @@ -206,6 +217,6 @@ public final class Provider implements Parcelable { @Override public int hashCode() { - return mainUrl().getHost().hashCode(); + return mainUrl().getDomain().hashCode(); } } -- cgit v1.2.3 From 8707f9e9a07f8c53955df14ef9b26d13a0eb60da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 27 Apr 2015 17:10:20 +0200 Subject: testEveryProvider also works --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 14 +++++++-- .../java/se/leap/bitmaskclient/EipFragment.java | 34 +++++----------------- 2 files changed, 18 insertions(+), 30 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index ddd03dbc..afc6b131 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -161,7 +161,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn providerToPreferences(provider); buildDashboard(false); - invalidateOptionsMenu(); + invalidateOptionsMenuOnUiThread(); if (data.hasExtra(SessionDialog.TAG)) { sessionDialog(Bundle.EMPTY); } @@ -322,7 +322,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn else hideUserSessionProgressBar(); changeSessionStatusMessage(user_session_status.toString()); - invalidateOptionsMenu(); + invalidateOptionsMenuOnUiThread(); } } @@ -432,7 +432,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); @@ -453,4 +452,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn 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/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index a13cab09..6decacb7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -111,10 +111,6 @@ public class EipFragment extends Fragment implements Observer { saveStatus(); } - void handleNewVpnCertificate() { - handleIcon(); - } - private void handleSwitchOn() { if (canStartEIP()) startEipFromScratch(); @@ -144,20 +140,20 @@ 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) { } @@ -193,13 +189,13 @@ 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) { } @@ -247,18 +243,10 @@ public class EipFragment extends Fragment implements Observer { dashboard.showLog(); VoidVpnService.stop(); } - adjustSwitch(); - } - - private void setConnectedUI() { - adjustSwitch(); - } - - private void setDisconnectedUI() { - adjustSwitch(); + updateIcon(); } - private void adjustSwitch() { + private void updateIcon() { if (eip_status.isConnected() || eip_status.isConnecting()) { if(eip_status.isConnecting()) { vpn_status_image.showProgress(true); @@ -273,13 +261,6 @@ public class EipFragment extends Fragment implements Observer { } } - private void setInProgressUI(EipStatus eip_status) { - adjustSwitch(); - } - - private void updatingCertificateUI() { - } - protected class EIPReceiver extends ResultReceiver { protected EIPReceiver(Handler handler) { @@ -320,7 +301,6 @@ public class EipFragment extends Fragment implements Observer { case Activity.RESULT_OK: break; case Activity.RESULT_CANCELED: - updatingCertificateUI(); dashboard.downloadVpnCertificate(); break; } -- cgit v1.2.3 From bd68fe662af7734d94a8853b38f418f19879e389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 27 Apr 2015 18:08:59 +0200 Subject: Added a button to the UI Turn on VPN touching that button, and leave the image as a mere indicator. --- .../main/java/se/leap/bitmaskclient/EipFragment.java | 19 +++++++++++++++++-- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 6decacb7..30147f65 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -20,6 +20,7 @@ import android.app.*; import android.content.*; import android.os.*; import android.view.*; +import android.widget.*; import org.jetbrains.annotations.*; @@ -37,10 +38,11 @@ public class EipFragment extends Fragment implements Observer { protected static final String IS_PENDING = TAG + ".is_pending"; protected static final String IS_CONNECTED = TAG + ".is_connected"; public static final String START_ON_BOOT = "start on boot"; - private static final String SHOWED_LOG = TAG + ".showed_log"; @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; @@ -101,7 +103,7 @@ public class EipFragment extends Fragment implements Observer { Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); } - @OnClick(R.id.vpn_Status_Image) + @OnClick(R.id.vpn_main_button) void handleIcon() { if (eip_status.isConnected() || eip_status.isConnecting()) handleSwitchOff(); @@ -244,6 +246,7 @@ public class EipFragment extends Fragment implements Observer { VoidVpnService.stop(); } updateIcon(); + updateButton(); } private void updateIcon() { @@ -261,6 +264,18 @@ public class EipFragment extends Fragment implements Observer { } } + 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 { protected EIPReceiver(Handler handler) { 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..171035d1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -20,6 +20,7 @@ import android.content.*; import com.google.gson.*; import com.google.gson.reflect.*; +import com.google.gson.stream.JsonWriter; import org.json.*; -- cgit v1.2.3 From f008b5ec8e1c74968e4a605d2de5423edf91b854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 29 Apr 2015 12:25:24 +0200 Subject: Creating a user session fragment. I've separated the user session management to it, and encapsulated ProviderAPICommand into its own class. Putting the fragment statically in dashboard.xml isn't working, Android complains about it being duplicated, so I'm going to add it dynamically. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 157 +++--------------- .../java/se/leap/bitmaskclient/EipFragment.java | 13 +- .../java/se/leap/bitmaskclient/LeapSRPSession.java | 2 +- .../main/java/se/leap/bitmaskclient/Provider.java | 2 +- .../se/leap/bitmaskclient/ProviderAPICommand.java | 45 +++++ .../java/se/leap/bitmaskclient/SessionDialog.java | 169 ------------------- app/src/main/java/se/leap/bitmaskclient/User.java | 44 ----- .../se/leap/bitmaskclient/UserSessionStatus.java | 109 ------------ .../bitmaskclient/userstatus/SessionDialog.java | 182 +++++++++++++++++++++ .../se/leap/bitmaskclient/userstatus/User.java | 45 +++++ .../userstatus/UserSessionFragment.java | 178 ++++++++++++++++++++ .../userstatus/UserSessionStatus.java | 119 ++++++++++++++ 12 files changed, 599 insertions(+), 466 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/SessionDialog.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/User.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/User.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index afc6b131..f541283a 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 * @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 = new Provider(); - private UserSessionStatus user_session_status; + UserSessionFragment user_session_fragment; + private static Provider provider = new Provider(); public ProviderAPIResultReceiver providerAPI_result_receiver; private boolean switching_provider; @@ -78,8 +73,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn super.onCreate(savedInstanceState); app = this; - user_session_status = UserSessionStatus.getInstance(getResources()); - user_session_status.addObserver(this); PRNGFixes.apply(); @@ -88,12 +81,16 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn handleVersion(); User.init(); + ProviderAPICommand.initialize(this); + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + restoreProvider(savedInstanceState); if (!provider.isConfigured()) startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP); else { buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); - restoreSessionStatus(savedInstanceState); + user_session_fragment.restoreSessionStatus(savedInstanceState); } } @@ -106,20 +103,9 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn 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, getResources()); - } - } - @Override protected void onSaveInstanceState(@NotNull Bundle outState) { 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()); - super.onSaveInstanceState(outState); } @@ -166,7 +152,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn 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,6 +199,8 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn ButterKnife.inject(this); provider_name.setText(provider.getDomain()); + user_session_fragment = new UserSessionFragment(); + if (provider.hasEIP()) { fragment_manager.removePreviousFragment(EipFragment.TAG); eip_fragment = new EipFragment(); @@ -229,7 +217,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn onBackPressed(); } } - handleNewUserSessionStatus(user_session_status); } @Override @@ -261,14 +248,14 @@ 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_session_fragment.logOut(); else switchProvider(); return true; case R.id.login_button: sessionDialog(Bundle.EMPTY); return true; case R.id.logout_button: - logOut(); + user_session_fragment.logOut(); return true; case R.id.signup_button: sessionDialog(Bundle.EMPTY); @@ -288,122 +275,18 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn log_window_wrapper.showLog(); } - @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()); - invalidateOptionsMenuOnUiThread(); - } - } - - 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); - } - }); - } - - 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) { - 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() { @@ -419,7 +302,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_session_fragment.logIn(username, password); } else if (resultCode == ProviderAPI.FAILED_SIGNUP) { sessionDialog(resultData); } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { @@ -447,6 +330,8 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn return app; } + public static Provider getProvider() { return provider; } + @Override public void startActivityForResult(Intent intent, int requestCode) { intent.putExtra(Dashboard.REQUEST_CODE, requestCode); diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 30147f65..4d1eb4bf 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -35,7 +35,7 @@ public class EipFragment extends Fragment implements Observer { public static String TAG = EipFragment.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"; public static final String START_ON_BOOT = "start on boot"; @@ -45,7 +45,7 @@ public class EipFragment extends Fragment implements Observer { Button main_button; private static Dashboard dashboard; - private static EIPReceiver mEIPReceiver; + private static EIPReceiver provider_api_receiver; private static EipStatus eip_status; private boolean wants_to_connect; @@ -53,7 +53,8 @@ public class EipFragment extends Fragment implements Observer { super.onAttach(activity); dashboard = (Dashboard) activity; - dashboard.providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.DOWNLOAD_EIP_SERVICE); + if(provider_api_receiver != null) + ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_EIP_SERVICE, provider_api_receiver); } @Override @@ -61,7 +62,7 @@ public class EipFragment extends Fragment implements Observer { super.onCreate(savedInstanceState); eip_status = EipStatus.getInstance(); eip_status.addObserver(this); - mEIPReceiver = new EIPReceiver(new Handler()); + provider_api_receiver = new EIPReceiver(new Handler()); } @Override @@ -219,7 +220,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, provider_api_receiver); dashboard.startService(vpn_intent); } @@ -335,6 +336,6 @@ public class EipFragment extends Fragment implements Observer { public static EIPReceiver getReceiver() { - return mEIPReceiver; + return provider_api_receiver; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index 1ced6d60..49cf3774 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java +++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java @@ -337,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/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index a66d53e7..559b47d1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -118,7 +118,7 @@ public final class Provider implements Parcelable { protected String certificatePin() { return certificate_pin; } - protected String getName() { + public String getName() { // Should we pass the locale in, or query the system here? String lang = Locale.getDefault().getLanguage(); String name = ""; 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/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java deleted file mode 100644 index 30344ff2..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java +++ /dev/null @@ -1,169 +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 . - */ -package se.leap.bitmaskclient; - -import android.app.*; -import android.content.*; -import android.os.*; -import android.view.*; -import android.widget.*; - -import butterknife.*; - -/** - * Implements the log in dialog, currently without progress dialog. - *

- * It returns to the previous fragment when finished, and sends username and password to the authenticate method. - *

- * It also notifies the user if the password is not valid. - * - * @author parmegv - */ -public class SessionDialog extends DialogFragment { - - - final public static String TAG = SessionDialog.class.getSimpleName(); - - final public static String USERNAME = "username"; - final public static String PASSWORD = "password"; - - public static enum ERRORS { - USERNAME_MISSING, - PASSWORD_INVALID_LENGTH, - RISEUP_WARNING - } - - @InjectView(R.id.user_message) - TextView user_message; - @InjectView(R.id.username_entered) - EditText username_field; - @InjectView(R.id.password_entered) - EditText password_field; - - private static boolean is_eip_pending = false; - - public SessionDialog() { - setArguments(Bundle.EMPTY); - } - - public AlertDialog onCreateDialog(Bundle savedInstanceState) { - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.session_dialog, null); - ButterKnife.inject(this, view); - - Bundle arguments = getArguments(); - if (arguments != Bundle.EMPTY) { - setUp(arguments); - } - - builder.setView(view) - .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String username = getEnteredUsername(); - String password = getEnteredPassword(); - dialog.dismiss(); - interface_with_Dashboard.logIn(username, password); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - interface_with_Dashboard.cancelLoginOrSignup(); - } - }) - .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String username = getEnteredUsername(); - String password = getEnteredPassword(); - dialog.dismiss(); - interface_with_Dashboard.signUp(username, password); - } - }); - - return builder.create(); - } - - private void setUp(Bundle arguments) { - is_eip_pending = arguments.getBoolean(EipFragment.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())) { - user_message.setVisibility(TextView.VISIBLE); - user_message.setText(R.string.login_riseup_warning); - } - if (arguments.containsKey(USERNAME)) { - String username = arguments.getString(USERNAME); - username_field.setText(username); - } - if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) { - username_field.setError(getString(R.string.username_ask)); - } - if (arguments.containsKey(getString(R.string.user_message))) { - user_message.setText(arguments.getString(getString(R.string.user_message))); - 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()) - password_field.requestFocus(); - - } - - private String getEnteredUsername() { - return username_field.getText().toString(); - } - - private String getEnteredPassword() { - return password_field.getText().toString(); - } - - - /** - * Interface used to communicate SessionDialog with Dashboard. - * - * @author parmegv - */ - public interface SessionDialogInterface { - public void logIn(String username, String password); - - public void signUp(String username, String password); - - public void cancelLoginOrSignup(); - } - - SessionDialogInterface interface_with_Dashboard; - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - interface_with_Dashboard = (SessionDialogInterface) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement LogInDialogListener"); - } - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - if (is_eip_pending) - interface_with_Dashboard.cancelLoginOrSignup(); - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/User.java deleted file mode 100644 index f3d3b8b1..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/User.java +++ /dev/null @@ -1,44 +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 . - */ -package se.leap.bitmaskclient; - -public class User { - private static String user_name = ""; - private static User user; - public static int DEFAULT_CONJUGATION_PERSON = 1; - - public static User init() { - if (user == null) { - user = new User(); - } - return user; - } - - public static void setUserName(String user_name) { - User.user_name = user_name; - } - - private User() { } - - public static String userName() { - return user_name; - } - - public static boolean loggedIn() { - return LeapSRPSession.loggedIn(); - } -} 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 28c7ecc7..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java +++ /dev/null @@ -1,109 +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 . - */ -package se.leap.bitmaskclient; - -import android.content.res.*; - -import java.util.*; - -public class UserSessionStatus extends Observable { - public static String TAG = UserSessionStatus.class.getSimpleName(); - private static UserSessionStatus 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.NOT_LOGGED_IN; - - public static UserSessionStatus getInstance(Resources resources) { - if (current_status == null) { - current_status = new UserSessionStatus(resources); - } - return current_status; - } - - private UserSessionStatus(Resources resources) { - UserSessionStatus.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 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_user, ""); - 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/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java new file mode 100644 index 00000000..f51a6779 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java @@ -0,0 +1,182 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.userstatus; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; +import android.widget.*; + +import butterknife.*; +import se.leap.bitmaskclient.EipFragment; +import se.leap.bitmaskclient.Provider; +import se.leap.bitmaskclient.R; + +/** + * Implements the log in dialog, currently without progress dialog. + *

+ * It returns to the previous fragment when finished, and sends username and password to the authenticate method. + *

+ * It also notifies the user if the password is not valid. + * + * @author parmegv + */ +public class SessionDialog extends DialogFragment { + + + final public static String TAG = SessionDialog.class.getSimpleName(); + + final public static String USERNAME = "username"; + final public static String PASSWORD = "password"; + + public static enum ERRORS { + USERNAME_MISSING, + PASSWORD_INVALID_LENGTH, + RISEUP_WARNING + } + + @InjectView(R.id.user_message) + TextView user_message; + @InjectView(R.id.username_entered) + EditText username_field; + @InjectView(R.id.password_entered) + EditText password_field; + + private static boolean is_eip_pending = false; + + 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) { + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.session_dialog, null); + ButterKnife.inject(this, view); + + Bundle arguments = getArguments(); + if (arguments != Bundle.EMPTY) { + setUp(arguments); + } + + builder.setView(view) + .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + String username = getEnteredUsername(); + String password = getEnteredPassword(); + dialog.dismiss(); + interface_with_Dashboard.logIn(username, password); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + interface_with_Dashboard.cancelLoginOrSignup(); + } + }) + .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + String username = getEnteredUsername(); + String password = getEnteredPassword(); + dialog.dismiss(); + interface_with_Dashboard.signUp(username, password); + } + }); + + return builder.create(); + } + + private void setUp(Bundle arguments) { + is_eip_pending = arguments.getBoolean(EipFragment.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())) { + user_message.setVisibility(TextView.VISIBLE); + user_message.setText(R.string.login_riseup_warning); + } + if (arguments.containsKey(USERNAME)) { + String username = arguments.getString(USERNAME); + username_field.setText(username); + } + if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) { + username_field.setError(getString(R.string.username_ask)); + } + if (arguments.containsKey(getString(R.string.user_message))) { + user_message.setText(arguments.getString(getString(R.string.user_message))); + 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()) + password_field.requestFocus(); + + } + + private String getEnteredUsername() { + return username_field.getText().toString(); + } + + private String getEnteredPassword() { + return password_field.getText().toString(); + } + + + /** + * Interface used to communicate SessionDialog with Dashboard. + * + * @author parmegv + */ + public interface SessionDialogInterface { + public void logIn(String username, String password); + + public void signUp(String username, String password); + + public void cancelLoginOrSignup(); + } + + SessionDialogInterface interface_with_Dashboard; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + interface_with_Dashboard = (SessionDialogInterface) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement LogInDialogListener"); + } + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + if (is_eip_pending) + interface_with_Dashboard.cancelLoginOrSignup(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java new file mode 100644 index 00000000..716e2ed6 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java @@ -0,0 +1,45 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.userstatus; + +import se.leap.bitmaskclient.LeapSRPSession; + +public class User { + private static String user_name = ""; + private static User user; + + public static User init() { + if (user == null) { + user = new User(); + } + return user; + } + + public static void setUserName(String user_name) { + User.user_name = user_name; + } + + private User() { } + + public static String userName() { + return user_name; + } + + public static boolean loggedIn() { + return LeapSRPSession.loggedIn(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java new file mode 100644 index 00000000..02b9fbeb --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java @@ -0,0 +1,178 @@ +package se.leap.bitmaskclient.userstatus; + +import android.app.*; +import android.os.*; +import android.view.*; +import android.widget.*; + +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +import butterknife.*; +import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.eip.EipStatus; + +public class UserSessionFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface { + + private static View view; + + public static String TAG = UserSessionFragment.class.getSimpleName(); + private static Dashboard dashboard; + private ProviderAPIResultReceiver providerAPI_result_receiver; + + @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; + @InjectView(R.id.user_session_button) + Button main_button; + + private UserSessionStatus user_session_status; + private boolean allows_registration = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + user_session_status = UserSessionStatus.getInstance(getResources()); + user_session_status.addObserver(this); + + handleNewUserSessionStatus(user_session_status); + } + + @Override + public void onSaveInstanceState(@NotNull Bundle outState) { + if (user_session_status_text_view != null && user_session_status_text_view.getVisibility() == TextView.VISIBLE) + outState.putSerializable(UserSessionStatus.TAG, user_session_status.sessionStatus()); + + super.onSaveInstanceState(outState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_user_session, container, false); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + Fragment fragment = (getFragmentManager().findFragmentById(R.id.user_session_fragment)); + FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); + ft.remove(fragment); + ft.commit(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + dashboard = (Dashboard) activity; + + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(dashboard); + } + + public 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, getResources()); + } + } + + @OnClick(R.id.user_session_button) + public void handleMainButton() { + if(user_session_status.isLoggedIn()) + logOut(); + else if(user_session_status.isLoggedOut()) + dashboard.sessionDialog(Bundle.EMPTY); + else if(user_session_status.inProgress()) + cancelLoginOrSignup(); + } + + @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 (allows_registration) { + if (user_session_status.inProgress()) + showUserSessionProgressBar(); + else + hideUserSessionProgressBar(); + changeSessionStatusMessage(); + updateButton(); + } + } + + private void showUserSessionProgressBar() { + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_progress_bar.setVisibility(ProgressBar.VISIBLE); + } + }); + } + + private void hideUserSessionProgressBar() { + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_progress_bar.setVisibility(ProgressBar.GONE); + } + }); + } + + private void changeSessionStatusMessage() { + final String message = user_session_status.toString(); + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_text_view.setText(message); + } + }); + } + + private void updateButton() { + if(User.loggedIn()) + main_button.setText(getString(R.string.logout_button)); + else if(allows_registration) + main_button.setText(getString(R.string.login_button)); + } + + + @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() { + 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; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java new file mode 100644 index 00000000..dec0e719 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java @@ -0,0 +1,119 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.userstatus; + +import android.content.res.*; + +import java.util.*; + +import se.leap.bitmaskclient.R; + +public class UserSessionStatus extends Observable { + public static String TAG = UserSessionStatus.class.getSimpleName(); + private static UserSessionStatus 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.NOT_LOGGED_IN; + + public static UserSessionStatus getInstance(Resources resources) { + if (current_status == null) { + current_status = new UserSessionStatus(resources); + } + return current_status; + } + + private UserSessionStatus(Resources resources) { + UserSessionStatus.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.LOGGING_IN; + } + + public boolean isLoggedOut() { + return session_status == SessionStatus.LOGGED_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_user, ""); + 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); + } +} -- cgit v1.2.3 From 8833acbafe00eb2941cfa052cb679fc2684b5290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 29 Apr 2015 12:47:43 +0200 Subject: Dynamically load user session fragment. Tests click new button, instead of action bar's. Fixing more bugs... --- app/src/main/java/se/leap/bitmaskclient/Dashboard.java | 1 + .../main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index f541283a..a854ffd4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -200,6 +200,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec provider_name.setText(provider.getDomain()); user_session_fragment = new UserSessionFragment(); + fragment_manager.replace(R.id.user_session_fragment, user_session_fragment, UserSessionFragment.TAG); if (provider.hasEIP()) { fragment_manager.removePreviousFragment(EipFragment.TAG); diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java index f51a6779..18f16301 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java @@ -81,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); } @@ -165,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_session_fragment);; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement LogInDialogListener"); -- cgit v1.2.3 From 9a54c425f6d96e1872899eabf78fb60082a8d234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 29 Apr 2015 18:21:03 +0200 Subject: Functional. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 7 +++-- .../java/se/leap/bitmaskclient/EipFragment.java | 12 ++++---- .../bitmaskclient/ProviderAPIResultReceiver.java | 3 +- .../userstatus/UserSessionFragment.java | 35 +++++++++++++++------- 4 files changed, 38 insertions(+), 19 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index a854ffd4..f87c9f94 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -82,8 +82,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec User.init(); ProviderAPICommand.initialize(this); - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), this); restoreProvider(savedInstanceState); if (!provider.isConfigured()) @@ -199,7 +198,11 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec ButterKnife.inject(this); provider_name.setText(provider.getDomain()); + user_session_fragment = new UserSessionFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean(Provider.ALLOW_REGISTRATION, provider.allowsRegistration()); + user_session_fragment.setArguments(bundle); fragment_manager.replace(R.id.user_session_fragment, user_session_fragment, UserSessionFragment.TAG); if (provider.hasEIP()) { diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 4d1eb4bf..5a7b2ced 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -45,7 +45,7 @@ public class EipFragment extends Fragment implements Observer { Button main_button; private static Dashboard dashboard; - private static EIPReceiver provider_api_receiver; + private static EIPReceiver eip_receiver; private static EipStatus eip_status; private boolean wants_to_connect; @@ -53,7 +53,9 @@ public class EipFragment extends Fragment implements Observer { super.onAttach(activity); dashboard = (Dashboard) activity; - if(provider_api_receiver != null) + ProviderAPIResultReceiver provider_api_receiver = new ProviderAPIResultReceiver(new Handler(), dashboard); + + if(eip_receiver != null) ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_EIP_SERVICE, provider_api_receiver); } @@ -62,7 +64,7 @@ public class EipFragment extends Fragment implements Observer { super.onCreate(savedInstanceState); eip_status = EipStatus.getInstance(); eip_status.addObserver(this); - provider_api_receiver = new EIPReceiver(new Handler()); + eip_receiver = new EIPReceiver(new Handler()); } @Override @@ -220,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, provider_api_receiver); + vpn_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); dashboard.startService(vpn_intent); } @@ -336,6 +338,6 @@ public class EipFragment extends Fragment implements Observer { public static EIPReceiver getReceiver() { - return provider_api_receiver; + return eip_receiver; } } 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/userstatus/UserSessionFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java index 02b9fbeb..dc334c3d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java @@ -15,8 +15,6 @@ import se.leap.bitmaskclient.eip.EipStatus; public class UserSessionFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface { - private static View view; - public static String TAG = UserSessionFragment.class.getSimpleName(); private static Dashboard dashboard; private ProviderAPIResultReceiver providerAPI_result_receiver; @@ -37,8 +35,6 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi user_session_status = UserSessionStatus.getInstance(getResources()); user_session_status.addObserver(this); - - handleNewUserSessionStatus(user_session_status); } @Override @@ -52,7 +48,15 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_user_session, container, false); + + View view = inflater.inflate(R.layout.fragment_user_session, container, false); + ButterKnife.inject(this, view); + + Bundle arguments = getArguments(); + allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION); + handleNewUserSessionStatus(user_session_status); + + return view; } @Override @@ -69,8 +73,7 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi super.onAttach(activity); dashboard = (Dashboard) activity; - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(dashboard); + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), dashboard); } public void restoreSessionStatus(Bundle savedInstanceState) { @@ -106,7 +109,7 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi showUserSessionProgressBar(); else hideUserSessionProgressBar(); - changeSessionStatusMessage(); + changeMessage(); updateButton(); } } @@ -129,7 +132,7 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi }); } - private void changeSessionStatusMessage() { + private void changeMessage() { final String message = user_session_status.toString(); dashboard.runOnUiThread(new Runnable() { @Override @@ -141,9 +144,19 @@ public class UserSessionFragment extends Fragment implements Observer, SessionDi private void updateButton() { if(User.loggedIn()) - main_button.setText(getString(R.string.logout_button)); + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + main_button.setText(dashboard.getString(R.string.logout_button)); + } + }); else if(allows_registration) - main_button.setText(getString(R.string.login_button)); + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + main_button.setText(dashboard.getString(R.string.login_button)); + } + }); } -- cgit v1.2.3 From 237e51e09ea7ae13c4cdf7fd9247447f6d75fb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 30 Apr 2015 13:51:43 +0200 Subject: Works smoothly, correct texts. Next step: beautify. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 26 +-- .../bitmaskclient/userstatus/SessionDialog.java | 2 +- .../se/leap/bitmaskclient/userstatus/User.java | 5 +- .../userstatus/UserSessionFragment.java | 191 --------------------- .../userstatus/UserSessionStatus.java | 119 ------------- .../leap/bitmaskclient/userstatus/UserStatus.java | 119 +++++++++++++ .../userstatus/UserStatusFragment.java | 178 +++++++++++++++++++ 7 files changed, 309 insertions(+), 331 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index f87c9f94..bf35d6c3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -63,7 +63,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec TextView provider_name; EipFragment eip_fragment; - UserSessionFragment user_session_fragment; + UserStatusFragment user_status_fragment; private static Provider provider = new Provider(); public ProviderAPIResultReceiver providerAPI_result_receiver; private boolean switching_provider; @@ -79,7 +79,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); - User.init(); + User.init(getString(R.string.default_username)); ProviderAPICommand.initialize(this); providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), this); @@ -89,7 +89,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP); else { buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); - user_session_fragment.restoreSessionStatus(savedInstanceState); + user_status_fragment.restoreSessionStatus(savedInstanceState); } } @@ -199,11 +199,11 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec provider_name.setText(provider.getDomain()); - user_session_fragment = new UserSessionFragment(); + user_status_fragment = new UserStatusFragment(); Bundle bundle = new Bundle(); bundle.putBoolean(Provider.ALLOW_REGISTRATION, provider.allowsRegistration()); - user_session_fragment.setArguments(bundle); - fragment_manager.replace(R.id.user_session_fragment, user_session_fragment, UserSessionFragment.TAG); + 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); @@ -227,10 +227,6 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec 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; } @@ -252,15 +248,9 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec return true; case R.id.switch_provider: switching_provider = true; - if (User.loggedIn()) user_session_fragment.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: - user_session_fragment.logOut(); - return true; case R.id.signup_button: sessionDialog(Bundle.EMPTY); return true; @@ -306,7 +296,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { String username = resultData.getString(SessionDialog.USERNAME); String password = resultData.getString(SessionDialog.PASSWORD); - user_session_fragment.logIn(username, password); + user_status_fragment.logIn(username, password); } else if (resultCode == ProviderAPI.FAILED_SIGNUP) { sessionDialog(resultData); } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java index 18f16301..f89418ba 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java @@ -167,7 +167,7 @@ public class SessionDialog extends DialogFragment { super.onAttach(activity); try { - interface_with_Dashboard = (SessionDialogInterface) activity.getFragmentManager().findFragmentById(R.id.user_session_fragment);; + 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/userstatus/User.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java index 716e2ed6..64ce0629 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/User.java @@ -19,12 +19,13 @@ package se.leap.bitmaskclient.userstatus; import se.leap.bitmaskclient.LeapSRPSession; public class User { - private static String user_name = ""; + private static String user_name; private static User user; - public static User init() { + public static User init(String default_username) { if (user == null) { user = new User(); + user.setUserName(default_username); } return user; } diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java deleted file mode 100644 index dc334c3d..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionFragment.java +++ /dev/null @@ -1,191 +0,0 @@ -package se.leap.bitmaskclient.userstatus; - -import android.app.*; -import android.os.*; -import android.view.*; -import android.widget.*; - -import org.jetbrains.annotations.NotNull; - -import java.util.*; - -import butterknife.*; -import se.leap.bitmaskclient.*; -import se.leap.bitmaskclient.eip.EipStatus; - -public class UserSessionFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface { - - public static String TAG = UserSessionFragment.class.getSimpleName(); - private static Dashboard dashboard; - private ProviderAPIResultReceiver providerAPI_result_receiver; - - @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; - @InjectView(R.id.user_session_button) - Button main_button; - - private UserSessionStatus user_session_status; - private boolean allows_registration = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - user_session_status = UserSessionStatus.getInstance(getResources()); - user_session_status.addObserver(this); - } - - @Override - public void onSaveInstanceState(@NotNull Bundle outState) { - if (user_session_status_text_view != null && user_session_status_text_view.getVisibility() == TextView.VISIBLE) - outState.putSerializable(UserSessionStatus.TAG, user_session_status.sessionStatus()); - - super.onSaveInstanceState(outState); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - View view = inflater.inflate(R.layout.fragment_user_session, container, false); - ButterKnife.inject(this, view); - - Bundle arguments = getArguments(); - allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION); - handleNewUserSessionStatus(user_session_status); - - return view; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - Fragment fragment = (getFragmentManager().findFragmentById(R.id.user_session_fragment)); - FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); - ft.remove(fragment); - ft.commit(); - } - - @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(UserSessionStatus.TAG)) { - UserSessionStatus.SessionStatus status = (UserSessionStatus.SessionStatus) savedInstanceState.getSerializable(UserSessionStatus.TAG); - user_session_status.updateStatus(status, getResources()); - } - } - - @OnClick(R.id.user_session_button) - public void handleMainButton() { - if(user_session_status.isLoggedIn()) - logOut(); - else if(user_session_status.isLoggedOut()) - dashboard.sessionDialog(Bundle.EMPTY); - else if(user_session_status.inProgress()) - cancelLoginOrSignup(); - } - - @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 (allows_registration) { - if (user_session_status.inProgress()) - showUserSessionProgressBar(); - else - hideUserSessionProgressBar(); - changeMessage(); - updateButton(); - } - } - - private void showUserSessionProgressBar() { - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - user_session_status_progress_bar.setVisibility(ProgressBar.VISIBLE); - } - }); - } - - private void hideUserSessionProgressBar() { - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - user_session_status_progress_bar.setVisibility(ProgressBar.GONE); - } - }); - } - - private void changeMessage() { - final String message = user_session_status.toString(); - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - user_session_status_text_view.setText(message); - } - }); - } - - private void updateButton() { - if(User.loggedIn()) - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - main_button.setText(dashboard.getString(R.string.logout_button)); - } - }); - else if(allows_registration) - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - main_button.setText(dashboard.getString(R.string.login_button)); - } - }); - } - - - @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() { - 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; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java deleted file mode 100644 index dec0e719..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserSessionStatus.java +++ /dev/null @@ -1,119 +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 . - */ -package se.leap.bitmaskclient.userstatus; - -import android.content.res.*; - -import java.util.*; - -import se.leap.bitmaskclient.R; - -public class UserSessionStatus extends Observable { - public static String TAG = UserSessionStatus.class.getSimpleName(); - private static UserSessionStatus 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.NOT_LOGGED_IN; - - public static UserSessionStatus getInstance(Resources resources) { - if (current_status == null) { - current_status = new UserSessionStatus(resources); - } - return current_status; - } - - private UserSessionStatus(Resources resources) { - UserSessionStatus.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.LOGGING_IN; - } - - public boolean isLoggedOut() { - return session_status == SessionStatus.LOGGED_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_user, ""); - 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/UserStatus.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java new file mode 100644 index 00000000..edfed8d6 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java @@ -0,0 +1,119 @@ +/** + * 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 . + */ +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 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..0766dbd5 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java @@ -0,0 +1,178 @@ +package se.leap.bitmaskclient.userstatus; + +import android.app.*; +import android.os.*; +import android.view.*; +import android.widget.*; + +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +import butterknife.*; +import mbanje.kurt.fabbutton.FabButton; +import se.leap.bitmaskclient.*; +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.fragment_user_session, container, false); + ButterKnife.inject(this, view); + + Bundle arguments = getArguments(); + allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION); + handleNewStatus(status); + + return view; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + Fragment fragment = (getFragmentManager().findFragmentById(R.id.user_status_fragment)); + FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); + ft.remove(fragment); + ft.commit(); + } + + @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()) + button.setText(dashboard.getString(R.string.logout_button)); + else if(allows_registration) { + if (status.isLoggedOut()) + 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; + } +} -- cgit v1.2.3 From 436de7afeea2cd234db8a4b70ace396101126e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 30 Apr 2015 19:09:31 +0200 Subject: Better layout, xlarge adaptation too. --- .../se/leap/bitmaskclient/userstatus/UserStatusFragment.java | 9 --------- 1 file changed, 9 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java index 0766dbd5..f0f4a8fa 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java @@ -60,15 +60,6 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia return view; } - @Override - public void onDestroyView() { - super.onDestroyView(); - Fragment fragment = (getFragmentManager().findFragmentById(R.id.user_status_fragment)); - FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); - ft.remove(fragment); - ft.commit(); - } - @Override public void onAttach(Activity activity) { super.onAttach(activity); -- cgit v1.2.3 From 5cc63073c78f0792ea462f0c2119ce5d361e9c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 1 May 2015 11:25:40 +0200 Subject: Separated tests for VpnFragment. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 10 +- .../java/se/leap/bitmaskclient/EipFragment.java | 343 --------------------- .../java/se/leap/bitmaskclient/VpnFragment.java | 343 +++++++++++++++++++++ .../main/java/se/leap/bitmaskclient/eip/EIP.java | 2 +- .../bitmaskclient/userstatus/SessionDialog.java | 4 +- 5 files changed, 351 insertions(+), 351 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/EipFragment.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/VpnFragment.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index bf35d6c3..bdc36e89 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -62,7 +62,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec @InjectView(R.id.providerName) TextView provider_name; - EipFragment eip_fragment; + VpnFragment eip_fragment; UserStatusFragment user_status_fragment; private static Provider provider = new Provider(); public ProviderAPIResultReceiver providerAPI_result_receiver; @@ -206,17 +206,17 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec 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(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java deleted file mode 100644 index 5a7b2ced..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ /dev/null @@ -1,343 +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 . - */ -package se.leap.bitmaskclient; - -import android.app.*; -import android.content.*; -import android.os.*; -import android.view.*; -import android.widget.*; - -import org.jetbrains.annotations.*; - -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 static String TAG = EipFragment.class.getSimpleName(); - - public static final String IS_PENDING = TAG + ".is_pending"; - protected static final String IS_CONNECTED = TAG + ".is_connected"; - public static final String START_ON_BOOT = "start on boot"; - - @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 eip_receiver; - private static EipStatus eip_status; - private boolean wants_to_connect; - - public void onAttach(Activity activity) { - super.onAttach(activity); - - dashboard = (Dashboard) activity; - 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 - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - eip_status = EipStatus.getInstance(); - eip_status.addObserver(this); - eip_receiver = new EIPReceiver(new Handler()); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.eip_service_fragment, container, false); - ButterKnife.inject(this, view); - - Bundle arguments = getArguments(); - if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT)) - startEipFromScratch(); - if (savedInstanceState != null) restoreState(savedInstanceState); - - return view; - } - - private void restoreState(@NotNull Bundle savedInstanceState) { - if (savedInstanceState.getBoolean(IS_PENDING)) - eip_status.setConnecting(); - else if (savedInstanceState.getBoolean(IS_CONNECTED)) - eip_status.setConnectedOrDisconnected(); - } - - @Override - public void onResume() { - super.onResume(); - eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); - handleNewState(eip_status); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - outState.putBoolean(IS_PENDING, eip_status.isConnecting()); - outState.putBoolean(IS_CONNECTED, eip_status.isConnected()); - super.onSaveInstanceState(outState); - } - - protected void saveStatus() { - boolean is_on = eip_status.isConnected() || eip_status.isConnecting(); - Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); - } - - @OnClick(R.id.vpn_main_button) - void handleIcon() { - if (eip_status.isConnected() || eip_status.isConnecting()) - handleSwitchOff(); - else - handleSwitchOn(); - - saveStatus(); - } - - private void handleSwitchOn() { - if (canStartEIP()) - startEipFromScratch(); - else if (canLogInToStartEIP()) { - wants_to_connect = true; - Bundle bundle = new Bundle(); - bundle.putBoolean(IS_PENDING, true); - dashboard.sessionDialog(bundle); - } - } - - private boolean canStartEIP() { - boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); - boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); - return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); - } - - private boolean canLogInToStartEIP() { - boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false); - boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); - return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected(); - } - - private void handleSwitchOff() { - if (eip_status.isConnecting()) { - askPendingStartCancellation(); - } else if (eip_status.isConnected()) { - askToStopEIP(); - } else - 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((android.R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - askToStopEIP(); - } - }) - .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - }) - .show(); - } - - public void startEipFromScratch() { - wants_to_connect = false; - eip_status.setConnecting(); - - saveStatus(); - eipCommand(Constants.ACTION_START_EIP); - } - - private void stop() { - if (eip_status.isConnecting()) - VoidVpnService.stop(); - disconnect(); - } - - private void disconnect() { - Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class); - dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); - eip_status.setDisconnecting(); - } - - protected void stopEipIfPossible() { - eipCommand(Constants.ACTION_STOP_EIP); - } - - private void askToStopEIP() { - 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((android.R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - stopEipIfPossible(); - } - }) - .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - }) - .show(); - } - - protected void updateEipService() { - eipCommand(Constants.ACTION_UPDATE_EIP_SERVICE); - } - - /** - * Send a command to EIP - * - * @param action A valid String constant from EIP class representing an Intent - * filter for the EIP class - */ - private void eipCommand(String action) { - // 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, eip_receiver); - dashboard.startService(vpn_intent); - } - - @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - eip_status = (EipStatus) observable; - final EipStatus eip_status = (EipStatus) observable; - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - handleNewState(eip_status); - } - }); - } - } - - private void handleNewState(EipStatus eip_status) { - Context context = dashboard.getApplicationContext(); - String error = eip_status.lastError(5, context); - - if (!error.isEmpty()) { - dashboard.showLog(); - VoidVpnService.stop(); - } - 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 { - vpn_status_image.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline); - vpn_status_image.showProgress(false); - } - } - - 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 { - - protected EIPReceiver(Handler handler) { - super(handler); - } - - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - super.onReceiveResult(resultCode, resultData); - - String request = resultData.getString(Constants.REQUEST_TAG); - - if (request.equals(Constants.ACTION_START_EIP)) { - switch (resultCode) { - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - - break; - } - } else if (request.equals(Constants.ACTION_STOP_EIP)) { - switch (resultCode) { - case Activity.RESULT_OK: - stop(); - break; - case Activity.RESULT_CANCELED: - break; - } - } else if (request.equals(Constants.EIP_NOTIFICATION)) { - switch (resultCode) { - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - break; - } - } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) { - switch (resultCode) { - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - dashboard.downloadVpnCertificate(); - break; - } - } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) { - switch (resultCode) { - case Activity.RESULT_OK: - if (wants_to_connect) - startEipFromScratch(); - break; - case Activity.RESULT_CANCELED: - handleNewState(eip_status); - break; - } - } - } - } - - - public static EIPReceiver getReceiver() { - return eip_receiver; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java new file mode 100644 index 00000000..2e3d7524 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java @@ -0,0 +1,343 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; +import android.widget.*; + +import org.jetbrains.annotations.*; + +import java.util.*; + +import butterknife.*; +import de.blinkt.openvpn.activities.*; +import mbanje.kurt.fabbutton.*; +import se.leap.bitmaskclient.eip.*; + +public class VpnFragment extends Fragment implements Observer { + + public static String TAG = VpnFragment.class.getSimpleName(); + + public static final String IS_PENDING = TAG + ".is_pending"; + protected static final String IS_CONNECTED = TAG + ".is_connected"; + public static final String START_ON_BOOT = "start on boot"; + + @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 eip_receiver; + private static EipStatus eip_status; + private boolean wants_to_connect; + + public void onAttach(Activity activity) { + super.onAttach(activity); + + dashboard = (Dashboard) activity; + 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 + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + eip_status = EipStatus.getInstance(); + eip_status.addObserver(this); + eip_receiver = new EIPReceiver(new Handler()); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.eip_service_fragment, container, false); + ButterKnife.inject(this, view); + + Bundle arguments = getArguments(); + if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT)) + startEipFromScratch(); + if (savedInstanceState != null) restoreState(savedInstanceState); + + return view; + } + + private void restoreState(@NotNull Bundle savedInstanceState) { + if (savedInstanceState.getBoolean(IS_PENDING)) + eip_status.setConnecting(); + else if (savedInstanceState.getBoolean(IS_CONNECTED)) + eip_status.setConnectedOrDisconnected(); + } + + @Override + public void onResume() { + super.onResume(); + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); + handleNewState(eip_status); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putBoolean(IS_PENDING, eip_status.isConnecting()); + outState.putBoolean(IS_CONNECTED, eip_status.isConnected()); + super.onSaveInstanceState(outState); + } + + protected void saveStatus() { + boolean is_on = eip_status.isConnected() || eip_status.isConnecting(); + Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); + } + + @OnClick(R.id.vpn_main_button) + void handleIcon() { + if (eip_status.isConnected() || eip_status.isConnecting()) + handleSwitchOff(); + else + handleSwitchOn(); + + saveStatus(); + } + + private void handleSwitchOn() { + if (canStartEIP()) + startEipFromScratch(); + else if (canLogInToStartEIP()) { + wants_to_connect = true; + Bundle bundle = new Bundle(); + bundle.putBoolean(IS_PENDING, true); + dashboard.sessionDialog(bundle); + } + } + + private boolean canStartEIP() { + boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); + boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); + return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); + } + + private boolean canLogInToStartEIP() { + boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false); + boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); + return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected(); + } + + private void handleSwitchOff() { + if (eip_status.isConnecting()) { + askPendingStartCancellation(); + } else if (eip_status.isConnected()) { + askToStopEIP(); + } else + 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((android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + askToStopEIP(); + } + }) + .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }) + .show(); + } + + public void startEipFromScratch() { + wants_to_connect = false; + eip_status.setConnecting(); + + saveStatus(); + eipCommand(Constants.ACTION_START_EIP); + } + + private void stop() { + if (eip_status.isConnecting()) + VoidVpnService.stop(); + disconnect(); + } + + private void disconnect() { + Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class); + dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); + eip_status.setDisconnecting(); + } + + protected void stopEipIfPossible() { + eipCommand(Constants.ACTION_STOP_EIP); + } + + private void askToStopEIP() { + 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((android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + stopEipIfPossible(); + } + }) + .setNegativeButton(dashboard.getString(android.R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }) + .show(); + } + + protected void updateEipService() { + eipCommand(Constants.ACTION_UPDATE_EIP_SERVICE); + } + + /** + * Send a command to EIP + * + * @param action A valid String constant from EIP class representing an Intent + * filter for the EIP class + */ + private void eipCommand(String action) { + // 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, eip_receiver); + dashboard.startService(vpn_intent); + } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + eip_status = (EipStatus) observable; + final EipStatus eip_status = (EipStatus) observable; + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + handleNewState(eip_status); + } + }); + } + } + + private void handleNewState(EipStatus eip_status) { + Context context = dashboard.getApplicationContext(); + String error = eip_status.lastError(5, context); + + if (!error.isEmpty()) { + dashboard.showLog(); + VoidVpnService.stop(); + } + 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 { + vpn_status_image.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline); + vpn_status_image.showProgress(false); + } + } + + 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 { + + protected EIPReceiver(Handler handler) { + super(handler); + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); + + String request = resultData.getString(Constants.REQUEST_TAG); + + if (request.equals(Constants.ACTION_START_EIP)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + + break; + } + } else if (request.equals(Constants.ACTION_STOP_EIP)) { + switch (resultCode) { + case Activity.RESULT_OK: + stop(); + break; + case Activity.RESULT_CANCELED: + break; + } + } else if (request.equals(Constants.EIP_NOTIFICATION)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + break; + } + } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + dashboard.downloadVpnCertificate(); + break; + } + } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) { + switch (resultCode) { + case Activity.RESULT_OK: + if (wants_to_connect) + startEipFromScratch(); + break; + case Activity.RESULT_CANCELED: + handleNewState(eip_status); + break; + } + } + } + } + + + public static EIPReceiver getReceiver() { + 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/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java index f89418ba..7dbbe059 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java @@ -23,7 +23,7 @@ import android.view.*; import android.widget.*; import butterknife.*; -import se.leap.bitmaskclient.EipFragment; +import se.leap.bitmaskclient.VpnFragment; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.R; @@ -113,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())) { -- cgit v1.2.3 From 6d2e86277cdf02d3c731d963656e2c4a0f8fea5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 5 May 2015 11:28:01 +0200 Subject: Rename user session fragment, add icon resource. The FabButton doesn't scale the icon as big as I want it to be, and it doesn't let me set the size to "wrap_content" because the library sets the sizes to match_parent. I'm going to try to modify my fork of FabButton to see if I can obtain what I want in its demo: just an icon and the progress indicator, the icon as big as possible. --- .../java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java index f0f4a8fa..ed822116 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java @@ -50,9 +50,11 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_user_session, container, false); + View view = inflater.inflate(R.layout.user_session_fragment, container, false); ButterKnife.inject(this, view); + icon.setIcon(R.drawable.ic_account_circle, R.drawable.ic_account_circle); + Bundle arguments = getArguments(); allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION); handleNewStatus(status); -- cgit v1.2.3 From de63a99c74bb05c271b0c7a5903b6bfab9ec0a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 29 May 2015 10:33:51 +0200 Subject: Updated libraries, simplified user status fragment Updated butterknife, dagger, renderers, fabbuton and gson, as well as gradle plugin. --- .../se/leap/bitmaskclient/ProviderManager.java | 26 ++++++++++------- .../leap/bitmaskclient/userstatus/FabButton.java | 34 ++++++++++++++++++++++ .../userstatus/UserStatusFragment.java | 32 +++++++++++++------- 3 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index 220a71c8..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 { 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; } @@ -120,7 +121,8 @@ public class ProviderManager implements AdapteeCollection { public Set providers() { Set all_providers = new HashSet(); all_providers.addAll(default_providers); - all_providers.addAll(custom_providers); + if(custom_providers != null) + all_providers.addAll(custom_providers); return all_providers; } @@ -140,25 +142,27 @@ public class ProviderManager implements AdapteeCollection { } @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 elements) { - custom_providers.addAll(elements); + public boolean addAll(Collection elements) { + return custom_providers.addAll(elements); } @Override - public void removeAll(Collection 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/userstatus/FabButton.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java new file mode 100644 index 00000000..1bf1847c --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java @@ -0,0 +1,34 @@ +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); + } + + @Override + protected void init(Context context, AttributeSet attrs, int defStyle) { + super.init(context, attrs, defStyle); + super.init(context, attrs, defStyle); + } + + private CircleImageView getImage() { + return (CircleImageView) findViewById(R.id.fabbutton_circle); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java index ed822116..f670553f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java @@ -1,17 +1,29 @@ package se.leap.bitmaskclient.userstatus; -import android.app.*; -import android.os.*; -import android.view.*; -import android.widget.*; +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.*; - -import butterknife.*; -import mbanje.kurt.fabbutton.FabButton; -import se.leap.bitmaskclient.*; +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 { @@ -53,8 +65,6 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia View view = inflater.inflate(R.layout.user_session_fragment, container, false); ButterKnife.inject(this, view); - icon.setIcon(R.drawable.ic_account_circle, R.drawable.ic_account_circle); - Bundle arguments = getArguments(); allows_registration = arguments.getBoolean(Provider.ALLOW_REGISTRATION); handleNewStatus(status); -- cgit v1.2.3 From 7fec00203782c5bf3b95bf8b4702c8d5a4c5940d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 29 May 2015 11:32:09 +0200 Subject: Gateways manager added a gateway from string twice. Give more time to provider details fragment to appear, because debugging makes the code run slowly. --- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'app/src/main/java') 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 171035d1..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,20 +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.stream.JsonWriter; +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 @@ -66,7 +73,7 @@ public class GatewaysManager { } public void addFromString(String gateways) { - List gateways_list = new ArrayList(); + List gateways_list = new ArrayList<>(); try { gateways_list = new Gson().fromJson(gateways, list_type); } catch (JsonSyntaxException e) { @@ -76,7 +83,6 @@ public class GatewaysManager { if (gateways_list != null) { for (Gateway gateway : gateways_list) addGateway(gateway); - this.gateways.addAll(gateways_list); } } -- cgit v1.2.3 From 47e0180aaaaa5ba2cd921ebd28221ab27fd51b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 1 Jun 2015 11:15:40 +0200 Subject: Update user session button correctly on failure --- .../main/java/se/leap/bitmaskclient/userstatus/UserStatus.java | 8 ++++++++ .../java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java index edfed8d6..90ad0ffd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatus.java @@ -92,6 +92,14 @@ public class UserStatus extends Observable { 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); diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java index f670553f..20189904 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java @@ -138,10 +138,10 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia } private void updateButton() { - if(status.isLoggedIn()) + if(status.isLoggedIn() || status.didntLogOut()) button.setText(dashboard.getString(R.string.logout_button)); else if(allows_registration) { - if (status.isLoggedOut()) + 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)); -- cgit v1.2.3 From 27594eeae6f40a402bc3110f06d57975168e74e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 4 Jun 2015 19:20:15 +0200 Subject: ics-openvpn as a submodule! beautiful ics-openvpn is now officially on GitHub, and they track openssl and openvpn as submodules, so it's easier to update everything. Just a git submodule update --recursive. I've also set up soft links to native modules from ics-openvpn in app, so that we don't copy files in Gradle (which was causing problems with the submodules .git* files, not being copied). That makes the repo cleaner. --- app/src/main/java/de/blinkt/openvpn/LaunchVPN.java | 17 +- .../main/java/de/blinkt/openvpn/VpnProfile.java | 12 +- .../main/java/de/blinkt/openvpn/core/CIDRIP.java | 1 + .../java/de/blinkt/openvpn/core/ConfigParser.java | 39 +- .../blinkt/openvpn/core/ICSOpenVPNApplication.java | 1 - .../de/blinkt/openvpn/core/OpenVPNService.java | 100 ++-- .../de/blinkt/openvpn/core/ProfileManager.java | 318 +++++------ .../de/blinkt/openvpn/core/VPNLaunchHelper.java | 5 +- .../java/de/blinkt/openvpn/core/VpnStatus.java | 598 +++++++++++---------- .../de/blinkt/openvpn/fragments/LogFragment.java | 2 - .../org/spongycastle/util/encoders/Base64.java | 5 + .../spongycastle/util/encoders/Base64Encoder.java | 5 + .../org/spongycastle/util/encoders/Encoder.java | 5 + .../util/io/pem/PemGenerationException.java | 5 + .../org/spongycastle/util/io/pem/PemHeader.java | 5 + .../org/spongycastle/util/io/pem/PemObject.java | 5 + .../util/io/pem/PemObjectGenerator.java | 5 + .../org/spongycastle/util/io/pem/PemReader.java | 7 +- .../org/spongycastle/util/io/pem/PemWriter.java | 5 + 19 files changed, 578 insertions(+), 562 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index 0eb1d99c..f1d769e1 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,27 @@ 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) + 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); + 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 mAllowedAppsVpn = new HashSet(); 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) 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>> options = new HashMap>>(); private HashMap> meta = new HashMap>(); + 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 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 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 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 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> 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..ed3a5446 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 mDnslist = new Vector(); + private final Vector 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) { @@ -176,7 +172,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mNotificationManager.notify(OPENVPN_STATUS, notification); - //startForeground(OPENVPN_STATUS, notification); + startForeground(OPENVPN_STATUS, notification); } private int getIconByConnectionStatus(ConnectionStatus level) { @@ -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 env = new HashMap(); + HashMap 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,6 @@ 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; } else { mDisplayBytecount = false; } @@ -878,8 +849,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); } } @@ -902,7 +872,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true)); boolean lowpriority = !mNotificationAlwaysVisible; - //showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); + showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); } } 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 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 profiles=new HashMap(); - 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 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(); - SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE); - Set vlist = listpref.getStringSet("vpnlist", null); - Exception exp =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; + 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 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 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 args = new Vector(); + Vector 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..dc3fa1c7 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 logbuffer; + public static LinkedList logbuffer; - private static Vector logListener; - private static Vector stateListener; - private static Vector byteCountListener; + private static Vector logListener; + private static Vector stateListener; + private static Vector 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(); - logListener = new Vector(); - stateListener = new Vector(); - byteCountListener = new Vector(); - 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 CREATOR - = new Parcelable.Creator() { - public LogItem createFromParcel(Parcel in) { - return new LogItem(in); - } + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + 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,94 @@ public class VpnStatus { } } + public void saveLogToDisk(Context c) { + + 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 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; - - } + 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; + + } public static void updateStatePause(OpenVPNManagement.pauseReason pauseReason) { switch (pauseReason) { @@ -405,88 +414,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 +499,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 +523,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 +537,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; -- cgit v1.2.3 From ffb6d2fe8ddd69f0e7239fa9505dc255eed6b348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 4 Jun 2015 20:17:43 +0200 Subject: Updated bitmask branch from ics-openvpn fork, second notification --- app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app/src/main/java') 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 ed3a5446..f9cb9a86 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -172,7 +172,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mNotificationManager.notify(OPENVPN_STATUS, notification); - startForeground(OPENVPN_STATUS, notification); + //startForeground(OPENVPN_STATUS, notification); } private int getIconByConnectionStatus(ConnectionStatus level) { @@ -840,6 +840,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mDisplayBytecount = true; mConnecttime = System.currentTimeMillis(); lowpriority = true; + String ns = Context.NOTIFICATION_SERVICE; + NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); + mNotificationManager.cancel(OPENVPN_STATUS); } else { mDisplayBytecount = false; } @@ -849,7 +852,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // CONNECTED // Does not work :( String msg = getString(resid); - showNotification(msg + " " + logmessage, msg, lowpriority, 0, level); + // showNotification(msg + " " + logmessage, msg, lowpriority, 0, level); } } @@ -872,7 +875,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true)); boolean lowpriority = !mNotificationAlwaysVisible; - showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); + //showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); } } -- cgit v1.2.3 From 07745ed137cb8d546c1d1b1e94714518e9df7887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 10 Jun 2015 19:35:06 +0200 Subject: Handle "Cancel" button of the Android VPN permission dialog --- app/src/main/java/de/blinkt/openvpn/LaunchVPN.java | 26 ++++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index f1d769e1..90216a70 100644 --- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java @@ -121,18 +121,20 @@ public class LaunchVPN extends Activity { 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(); + } } } -- cgit v1.2.3 From 2d55413d913b4d6fc0f10900f80f13532ea74809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 11 Jun 2015 10:56:45 +0200 Subject: Update java and xml files --- app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/src/main/java') 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 dc3fa1c7..62a60643 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -312,8 +312,7 @@ public class VpnStatus { public void saveLogToDisk(Context c) { - new File(c.getCacheDir(), "log.xml"); - + File logOut = new File(c.getCacheDir(), "log.xml"); } -- cgit v1.2.3 From d1c6e3c1756cee8104a98718b70e2f3169d24a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 12 Jun 2015 17:01:35 +0200 Subject: Transparent background of the FabButton, yay! --- app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java | 6 ------ 1 file changed, 6 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java index 1bf1847c..d1c56dee 100644 --- a/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java +++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/FabButton.java @@ -22,12 +22,6 @@ public class FabButton extends mbanje.kurt.fabbutton.FabButton { super(context, attrs, defStyle); } - @Override - protected void init(Context context, AttributeSet attrs, int defStyle) { - super.init(context, attrs, defStyle); - super.init(context, attrs, defStyle); - } - private CircleImageView getImage() { return (CircleImageView) findViewById(R.id.fabbutton_circle); } -- cgit v1.2.3