summaryrefslogtreecommitdiff
path: root/src/se/leap/leapclient
diff options
context:
space:
mode:
authorSean Leonard <meanderingcode@aetherislands.net>2013-10-21 01:03:45 -0700
committerSean Leonard <meanderingcode@aetherislands.net>2013-10-21 01:03:45 -0700
commit5e43d1ea5436af16f227a98fee495f707c885a96 (patch)
tree072b13f104cf2da87db80b0a6b78214139ae0618 /src/se/leap/leapclient
parentf49967fb3f24bf0a22d09b5823bd174a45e758f7 (diff)
parentf21030aacec6b7f36ea1b8adc86769e3f0b8a9ad (diff)
Merge branch 'release-0.2.1'0.2.1
Diffstat (limited to 'src/se/leap/leapclient')
-rw-r--r--src/se/leap/leapclient/AboutFragment.java58
-rw-r--r--src/se/leap/leapclient/ConfigHelper.java382
-rw-r--r--src/se/leap/leapclient/ConfigurationWizard.java411
-rw-r--r--src/se/leap/leapclient/Dashboard.java350
-rw-r--r--src/se/leap/leapclient/EIP.java511
-rw-r--r--src/se/leap/leapclient/EipServiceFragment.java264
-rw-r--r--src/se/leap/leapclient/LeapHttpClient.java87
-rw-r--r--src/se/leap/leapclient/LeapSRPSession.java322
-rw-r--r--src/se/leap/leapclient/LogInDialog.java106
-rw-r--r--src/se/leap/leapclient/NewProviderDialog.java108
-rw-r--r--src/se/leap/leapclient/Provider.java194
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java733
-rw-r--r--src/se/leap/leapclient/ProviderAPIResultReceiver.java56
-rw-r--r--src/se/leap/leapclient/ProviderDetailFragment.java108
-rw-r--r--src/se/leap/leapclient/ProviderListContent.java141
-rw-r--r--src/se/leap/leapclient/ProviderListFragment.java191
16 files changed, 0 insertions, 4022 deletions
diff --git a/src/se/leap/leapclient/AboutFragment.java b/src/se/leap/leapclient/AboutFragment.java
deleted file mode 100644
index a3fbbf93..00000000
--- a/src/se/leap/leapclient/AboutFragment.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package se.leap.leapclient;
-
-import android.app.Fragment;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.text.Html;
-import android.text.Spanned;
-import android.text.method.LinkMovementMethod;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-import se.leap.leapclient.R;
-
-public class AboutFragment extends Fragment {
-
- public static Fragment newInstance() {
- AboutFragment provider_detail_fragment = new AboutFragment();
- return provider_detail_fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View v= inflater.inflate(R.layout.about, container, false);
- TextView ver = (TextView) v.findViewById(R.id.version);
-
- String version;
- String name="Openvpn";
- try {
- PackageInfo packageinfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
- version = packageinfo.versionName;
- name = getString(R.string.app);
- } catch (NameNotFoundException e) {
- version = "error fetching version";
- }
-
-
- ver.setText(getString(R.string.version_info,name,version));
-
- TextView translation = (TextView) v.findViewById(R.id.translation);
-
- // Don't print a text for myself
- if ( getString(R.string.translationby).contains("Arne Schwabe"))
- translation.setText("");
- else
- translation.setText(R.string.translationby);
- return v;
- }
-
-}
diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java
deleted file mode 100644
index 62ebf8f1..00000000
--- a/src/se/leap/leapclient/ConfigHelper.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package se.leap.leapclient;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.io.InputStream;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Environment;
-import android.util.Base64;
-
-/**
- * Stores constants, and implements auxiliary methods used across all LEAP Android classes.
- *
- * @author parmegv
- * @author MeanderingCode
- *
- */
-public class ConfigHelper {
-
- public static SharedPreferences shared_preferences;
- private static KeyStore keystore_trusted;
-
- final public static String
- ABOUT_FRAGMENT = "aboutFragment",
- DOWNLOAD_JSON_FILES_BUNDLE_EXTRA = "downloadJSONFiles",
- UPDATE_PROVIDER_DOTJSON = "updateProviderDotJSON",
- DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
- LOG_IN_DIALOG = "logInDialog",
- NEW_PROVIDER_DIALOG = "logInDialog",
- SRP_REGISTER = "srpRegister",
- SRP_AUTH = "srpAuth",
- M1_KEY = "M1",
- M2_KEY = "M2",
- LOG_IN = "logIn",
- LOG_OUT = "logOut",
- DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate",
- API_VERSION_KEY = "api_version",
- API_RETURN_SERIAL_KEY = "serial",
- RESULT_KEY = "result",
- RECEIVER_KEY = "receiver",
- PROVIDER_KEY = "provider",
- SERVICE_KEY = "service",
- ALLOWED_ANON = "allow_anonymous",
- MAIN_CERT_KEY = "main_cert",
- CERT_KEY = "cert",
- KEY_KEY = "key",
- EIP_SERVICE_KEY = "eip",
- EIP_PARSED_SERIAL = "eip_parsed_serial",
- TYPE_OF_CERTIFICATE = "type_of_certificate",
- ANON_CERTIFICATE = "anon_certificate",
- AUTHED_CERTIFICATE = "authed_certificate",
- SALT_KEY = "salt",
- SESSION_ID_COOKIE_KEY = "session_id_cookie_key",
- SESSION_ID_KEY = "session_id",
- PREFERENCES_KEY = "LEAPPreferences",
- USER_DIRECTORY = "leap_android",
- PROVIDER_NAME = "provider_name",
- PROVIDER_ID = "provider_id",
- PROVIDER_MAIN_URL = "provider_main_url",
- PROVIDER_JSON_URL = "provider_json_url",
- CUSTOM = "custom",
- DANGER_ON = "danger_on",
- API_URL_KEY = "api_uri",
- USERNAME_KEY = "username",
- PASSWORD_KEY = "password",
- ALLOW_REGISTRATION_KEY = "allow_registration",
- EIP_SERVICE_API_PATH = "config/eip-service.json",
- ERRORS_KEY = "errors",
- RECEIVER_TAG = "receiverTag",
- REQUEST_TAG = "requestTag",
- PROVIDER_DETAILS_DIALOG = "providerDetailsFragment",
- DOMAIN = "domain",
- NAME = "name",
- DESCRIPTION = "description",
- QUIT = "quit"
- ;
-
- final public static String NG_1024 =
- "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3";
- final public static BigInteger G = new BigInteger("2");
-
- final public static int
- CUSTOM_PROVIDER_ADDED = 0,
- CORRECTLY_DOWNLOADED_JSON_FILES = 1,
- INCORRECTLY_DOWNLOADED_JSON_FILES = 2,
- SRP_AUTHENTICATION_SUCCESSFUL = 3,
- SRP_AUTHENTICATION_FAILED = 4,
- SRP_REGISTRATION_SUCCESSFUL = 5,
- SRP_REGISTRATION_FAILED = 6,
- LOGOUT_SUCCESSFUL = 7,
- LOGOUT_FAILED = 8,
- CORRECTLY_DOWNLOADED_CERTIFICATE = 9,
- INCORRECTLY_DOWNLOADED_CERTIFICATE = 10,
- CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11,
- INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12,
- CORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 13,
- INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14
- ;
-
-
- private static boolean checkSharedPrefs() {
- try {
- shared_preferences = Dashboard.getAppContext().getSharedPreferences(PREFERENCES_KEY,Context.MODE_PRIVATE);
- } catch (Exception e) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Saves a JSON object into class scope Shared Preferences
- * @param shared_preferences_key
- * @param content
- */
- public static void saveSharedPref(String shared_preferences_key, JSONObject content) {
-
- SharedPreferences.Editor shared_preferences_editor = shared_preferences
- .edit();
- shared_preferences_editor.putString(shared_preferences_key,
- content.toString());
- shared_preferences_editor.commit();
- }
-
- /**
- * Saves a String object into class scope Shared Preferences
- * @param shared_preferences_key
- * @param content
- */
- public static void saveSharedPref(String shared_preferences_key, String content) {
-
- SharedPreferences.Editor shared_preferences_editor = shared_preferences
- .edit();
- shared_preferences_editor.putString(shared_preferences_key,
- content);
- shared_preferences_editor.commit();
- }
-
- /**
- * Saves a boolean object into class scope Shared Preferences
- * @param shared_preferences_key
- * @param content
- */
- public static void saveSharedPref(String shared_preferences_key, boolean content) {
-
- SharedPreferences.Editor shared_preferences_editor = shared_preferences
- .edit();
- shared_preferences_editor.putBoolean(shared_preferences_key, content);
- shared_preferences_editor.commit();
- }
-
- /**
- * Saves an int into class scope Shared Preferences
- *
- * @param shared_preferences_key
- * @param value
- */
- protected static void saveSharedPref(String shared_preferences_key, int value) {
- SharedPreferences.Editor shared_preferences_editor = shared_preferences.edit();
- shared_preferences_editor.putInt(shared_preferences_key, value).commit();
- }
-
- /**
- * Gets String object from class scope Shared Preferences
- * @param shared_preferences_key
- * @return the string correspondent to the key parameter
- */
- public static String getStringFromSharedPref(String shared_preferences_key) {
- String content = null;
- content = shared_preferences.getString(shared_preferences_key, "");
- return content;
- }
-
- /**
- * Gets JSON object from class scope Shared Preferences
- * @param shared_preferences_key
- * @return the JSON object correspondent to the key parameter
- */
- public static JSONObject getJsonFromSharedPref(String shared_preferences_key) throws JSONException {
- JSONObject content = null;
- if ( checkSharedPrefs() ) {
- String json_string = shared_preferences.getString(shared_preferences_key, "");
- content = new JSONObject(json_string);
- }
-
- return content;
- }
-
- /*
- * This method defaults to false.
- * If you use this method, be sure to fail-closed on false!
- * TODO This is obviously less than ideal...solve it!
- */
- public static boolean getBoolFromSharedPref(String shared_preferences_key) {
- boolean value = false;
- if ( checkSharedPrefs() ) {
- value = shared_preferences.getBoolean(shared_preferences_key, false);
- }
- return value;
- }
-
- /**
- * Get an int from SharedPreferences
- *
- * @param shared_preferences_key Key to retrieve
- * @return The value for the key or 0
- */
- protected static int getIntFromSharedPref(String shared_preferences_key) {
- return shared_preferences.getInt(shared_preferences_key, 0);
- }
-
- /*
- * This method defaults to false.
- * If you use this method, be sure to fail-closed on false!
- * TODO This is obviously less than ideal...solve it!
- */
- public static boolean removeFromSharedPref(String shared_preferences_key) {
- SharedPreferences.Editor shared_preferences_editor = shared_preferences
- .edit();
- shared_preferences_editor.remove(shared_preferences_key);
- return shared_preferences_editor.commit();
- }
-
- /**
- * Opens a FileInputStream from the user directory of the external storage directory.
- * @param filename
- * @return a file input stream
- */
- public static FileInputStream openFileInputStream(String filename) {
- FileInputStream input_stream = null;
- File root = Environment.getExternalStorageDirectory();
- File leap_dir = new File(root.getAbsolutePath() + File.separator + USER_DIRECTORY);
- try {
- input_stream = new FileInputStream(leap_dir + File.separator + filename);
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return input_stream;
- }
-
- /**
- * Treat the input as the MSB representation of a number,
- * and lop off leading zero elements. For efficiency, the
- * input is simply returned if no leading zeroes are found.
- *
- * @param in array to be trimmed
- */
- public static byte[] trim(byte[] in) {
- if(in.length == 0 || in[0] != 0)
- return in;
-
- int len = in.length;
- int i = 1;
- while(in[i] == 0 && i < len)
- ++i;
- byte[] ret = new byte[len - i];
- System.arraycopy(in, i, ret, 0, len - i);
- return ret;
- }
-
- /**
- * Sets class scope Shared Preferences
- * @param shared_preferences
- */
- public static void setSharedPreferences(
- SharedPreferences shared_preferences) {
- ConfigHelper.shared_preferences = shared_preferences;
- }
-
- public static X509Certificate parseX509CertificateFromString(String certificate_string) {
- java.security.cert.Certificate certificate = null;
- CertificateFactory cf;
- try {
- cf = CertificateFactory.getInstance("X.509");
-
- certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
- byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT);
- InputStream caInput = new ByteArrayInputStream(cert_bytes);
- try {
- certificate = cf.generateCertificate(caInput);
- System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN());
- } finally {
- caInput.close();
- }
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- return null;
- }
-
- return (X509Certificate) certificate;
- }
-
- /**
- * Adds a new X509 certificate given its input stream and its provider name
- * @param provider used to store the certificate in the keystore
- * @param inputStream from which X509 certificate must be generated.
- */
- public static void addTrustedCertificate(String provider, InputStream inputStream) {
- CertificateFactory cf;
- try {
- cf = CertificateFactory.getInstance("X.509");
- X509Certificate cert =
- (X509Certificate)cf.generateCertificate(inputStream);
- keystore_trusted.setCertificateEntry(provider, cert);
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (KeyStoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Adds a new X509 certificate given in its string from and using its provider name
- * @param provider used to store the certificate in the keystore
- * @param certificate
- */
- public static void addTrustedCertificate(String provider, String certificate) {
-
- try {
- X509Certificate cert = ConfigHelper.parseX509CertificateFromString(certificate);
- if(keystore_trusted == null) {
- keystore_trusted = KeyStore.getInstance("BKS");
- keystore_trusted.load(null);
- }
- keystore_trusted.setCertificateEntry(provider, cert);
- } catch (KeyStoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * @return class wide keystore
- */
- public static KeyStore getKeystore() {
- return keystore_trusted;
- }
-}
diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java
deleted file mode 100644
index 934e2ea0..00000000
--- a/src/se/leap/leapclient/ConfigurationWizard.java
+++ /dev/null
@@ -1,411 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.io.IOException;
-import java.util.Iterator;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.leapclient.ProviderAPIResultReceiver.Receiver;
-import se.leap.leapclient.ProviderListContent.ProviderItem;
-import se.leap.leapclient.R;
-import se.leap.openvpn.MainActivity;
-import android.app.Activity;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Activity that builds and shows the list of known available providers.
- *
- * It also allows the user to enter custom providers with a button.
- *
- * @author parmegv
- *
- */
-public class ConfigurationWizard extends Activity
-implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, ProviderDetailFragment.ProviderDetailFragmentInterface, Receiver {
-
- private ProviderItem mSelectedProvider;
- private ProgressDialog mProgressDialog;
- private Intent mConfigState = new Intent();
-
- protected static final String PROVIDER_SET = "PROVIDER SET";
- protected static final String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
-
- public ProviderAPIResultReceiver providerAPI_result_receiver;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.configuration_wizard_activity);
-
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- ConfigHelper.setSharedPreferences(getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE));
-
- loadPreseededProviders();
-
- // Only create our fragments if we're not restoring a saved instance
- if ( savedInstanceState == null ){
- // TODO Some welcome screen?
- // We will need better flow control when we have more Fragments (e.g. user auth)
- ProviderListFragment providerList = new ProviderListFragment();
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .add(R.id.configuration_wizard_layout, providerList, "providerlist")
- .commit();
- }
-
- // TODO: If exposing deep links into your app, handle intents here.
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(resultData.getString(ConfigHelper.PROVIDER_KEY));
- boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON);
- ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json);
- ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on);
- ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
- mConfigState.setAction(PROVIDER_SET);
-
- if(mProgressDialog != null) mProgressDialog.dismiss();
- mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true);
- mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services));
- if(resultData.containsKey(ConfigHelper.PROVIDER_ID))
- mSelectedProvider = getProvider(resultData.getString(ConfigHelper.PROVIDER_ID));
-
- ProviderListFragment providerList = new ProviderListFragment();
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, providerList, "providerlist")
- .commit();
- downloadJSONFiles(mSelectedProvider);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
-
- mProgressDialog.dismiss();
- //Toast.makeText(this, getResources().getString(R.string.config_error_parsing), Toast.LENGTH_LONG);
- setResult(RESULT_CANCELED, mConfigState);
- }
- }
- else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
- mProgressDialog.dismiss();
- setResult(RESULT_CANCELED, mConfigState);
- }
- else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) {
- if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){
- mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_certificates));
- mConfigState.putExtra(SERVICES_RETRIEVED, true);
- downloadAnonCert();
- } else {
- mProgressDialog.dismiss();
- //Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show();
- setResult(RESULT_OK);
- finish();
- }
- }
- else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) {
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message, Toast.LENGTH_LONG).show();
- setResult(RESULT_CANCELED, mConfigState);
- }
- else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- mProgressDialog.dismiss();
- setResult(RESULT_OK);
- showProviderDetails(getCurrentFocus());
- } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- mProgressDialog.dismiss();
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_certificate_message, Toast.LENGTH_LONG).show();
- setResult(RESULT_CANCELED, mConfigState);
- }
- }
-
- /**
- * Callback method from {@link ProviderListFragment.Callbacks}
- * indicating that the item with the given ID was selected.
- */
- @Override
- public void onItemSelected(String id) {
- //TODO Code 2 pane view
- ProviderItem selected_provider = getProvider(id);
- mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true);
- mSelectedProvider = selected_provider;
- saveProviderJson(mSelectedProvider);
- }
-
- @Override
- public void onBackPressed() {
- try {
- if(ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY) == null || ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY).length() == 0) {
- askDashboardToQuitApp();
- } else {
- setResult(RESULT_OK);
- }
- } catch (JSONException e) {
- askDashboardToQuitApp();
- }
- super.onBackPressed();
- }
-
- private void askDashboardToQuitApp() {
- Intent ask_quit = new Intent();
- ask_quit.putExtra(ConfigHelper.QUIT, ConfigHelper.QUIT);
- setResult(RESULT_CANCELED, ask_quit);
- }
-
- private ProviderItem getProvider(String id) {
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.id.equalsIgnoreCase(id)) {
- return provider;
- }
- }
- return null;
- }
-
- /**
- * Loads providers data from url file contained in the project
- * @return true if the file was read correctly
- */
- private boolean loadPreseededProviders() {
- boolean loaded_preseeded_providers = false;
- AssetManager asset_manager = getAssets();
- String[] urls_filepaths = null;
- try {
- String url_files_folder = "urls";
- //TODO Put that folder in a better place (also inside the "for")
- urls_filepaths = asset_manager.list(url_files_folder);
- String provider_name = "";
- for(String url_filepath : urls_filepaths)
- {
- boolean custom = false;
- provider_name = url_filepath.subSequence(0, url_filepath.indexOf(".")).toString();
- if(ProviderListContent.ITEMS.isEmpty()) //TODO I have to implement a way of checking if a provider new or is already present in that ITEMS list
- ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath), custom, true)); // By default, it trusts the provider
- loaded_preseeded_providers = true;
- }
- } catch (IOException e) {
- loaded_preseeded_providers = false;
- }
-
- return loaded_preseeded_providers;
- }
-
- /**
- * Saves provider.json file associated with provider.
- *
- * If the provider is custom, the file has already been downloaded so we load it from memory.
- * If not, the file is updated using the provider's URL.
- * @param provider
- */
- private void saveProviderJson(ProviderItem provider) {
- JSONObject provider_json = new JSONObject();
- try {
- if(!provider.custom) {
- updateProviderDotJson(provider.name, provider.provider_json_url, provider.danger_on);
- } else {
- // FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ?
- // I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software?
- // If not, we should just be getting names/urls, and fetching the provider.json like in custom entries
- provider_json = provider.provider_json;
- ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json);
- ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
- ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, provider.danger_on);
-
- mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services));
- downloadJSONFiles(mSelectedProvider);
- }
- } catch (JSONException e) {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
-
- /**
- * Asks ProviderAPI to download provider site's certificate and eip-service.json
- *
- * URLs are fetched from the provider parameter
- * @param provider from which certificate and eip-service.json files are going to be downloaded
- */
- private void downloadJSONFiles(ProviderItem provider) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
-
- method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, provider.name);
- method_and_parameters.putString(ConfigHelper.MAIN_CERT_KEY, provider.cert_json_url);
- method_and_parameters.putString(ConfigHelper.EIP_SERVICE_KEY, provider.eip_service_json_url);
- method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, provider.danger_on);
-
- provider_API_command.putExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
-
- /**
- * Asks ProviderAPI to download an anonymous (anon) VPN certificate.
- */
- private void downloadAnonCert() {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
-
- method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE);
-
- provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
-
- /**
- * Open the new provider dialog
- * @param view from which the dialog is showed
- */
- public void addAndSelectNewProvider(View view) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG);
- if (previous_new_provider_dialog != null) {
- fragment_transaction.remove(previous_new_provider_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = NewProviderDialog.newInstance();
- newFragment.show(fragment_transaction, ConfigHelper.NEW_PROVIDER_DIALOG);
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- */
- public void showProviderDetails(View view) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_provider_details_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.PROVIDER_DETAILS_DIALOG);
- if (previous_provider_details_dialog != null) {
- fragment_transaction.remove(previous_provider_details_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = ProviderDetailFragment.newInstance();
- newFragment.show(fragment_transaction, ConfigHelper.PROVIDER_DETAILS_DIALOG);
- }
-
- @Override
- public void saveAndSelectProvider(String provider_main_url, boolean danger_on) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
- method_and_parameters.putString(ConfigHelper.PROVIDER_MAIN_URL, provider_main_url);
- method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, danger_on);
-
- provider_API_command.putExtra(ConfigHelper.DOWNLOAD_NEW_PROVIDER_DOTJSON, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
-
- /**
- * Asks ProviderAPI to download a new provider.json file
- * @param provider_name
- * @param provider_json_url
- * @param danger_on tells if HTTPS client should bypass certificate errors
- */
- public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
- method_and_parameters.putString(ConfigHelper.PROVIDER_NAME, provider_name);
- method_and_parameters.putString(ConfigHelper.PROVIDER_JSON_URL, provider_json_url);
- method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, danger_on);
-
- provider_API_command.putExtra(ConfigHelper.UPDATE_PROVIDER_DOTJSON, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item){
- switch (item.getItemId()){
- case R.id.about_leap:
- showAboutFragment(getCurrentFocus());
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- */
- public void showAboutFragment(View view) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_about_fragment = getFragmentManager().findFragmentByTag(ConfigHelper.ABOUT_FRAGMENT);
- if (previous_about_fragment == null) {
- fragment_transaction.addToBackStack(null);
-
- Fragment newFragment = AboutFragment.newInstance();
- fragment_transaction.replace(R.id.configuration_wizard_layout, newFragment, ConfigHelper.ABOUT_FRAGMENT).commit();
- }
- }
-
- @Override
- public void login() {
- Intent ask_login = new Intent();
- ask_login.putExtra(ConfigHelper.LOG_IN, ConfigHelper.LOG_IN);
- setResult(RESULT_OK, ask_login);
- finish();
- }
-
- @Override
- public void use_anonymously() {
- setResult(RESULT_OK);
- finish();
- }
-}
diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java
deleted file mode 100644
index 063cd3cd..00000000
--- a/src/se/leap/leapclient/Dashboard.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import org.apache.http.cookie.Cookie;
-import org.apache.http.impl.cookie.BasicClientCookie;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.leapclient.ProviderAPIResultReceiver.Receiver;
-import se.leap.openvpn.MainActivity;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * The main user facing Activity of LEAP Android, consisting of status, controls,
- * and access to preferences.
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
-public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface,Receiver {
-
- protected static final int CONFIGURE_LEAP = 0;
-
- private static final String TAG_EIP_FRAGMENT = "EIP_DASHBOARD_FRAGMENT";
-
- private ProgressDialog mProgressDialog;
-
- private static Context app;
- private static SharedPreferences preferences;
- private static Provider provider;
-
- private TextView providerNameTV;
-
- private boolean authed = false;
-
- public ProviderAPIResultReceiver providerAPI_result_receiver;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- app = this;
-
- ConfigHelper.setSharedPreferences(getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE));
- preferences = ConfigHelper.shared_preferences;
-
- if (ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY).isEmpty())
- startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
- else
- buildDashboard();
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data){
- if ( requestCode == CONFIGURE_LEAP ) {
- if ( resultCode == RESULT_OK ){
- startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) );
- buildDashboard();
- if(data != null && data.hasExtra(ConfigHelper.LOG_IN)) {
- View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(view, "");
- }
- } else if(resultCode == RESULT_CANCELED && data.hasExtra(ConfigHelper.QUIT)) {
- finish();
- } else
- configErrorDialog();
- }
- }
-
- /**
- * Dialog shown when encountering a configuration error. Such errors require
- * reconfiguring LEAP or aborting the application.
- */
- private void configErrorDialog() {
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext());
- alertBuilder.setTitle(getResources().getString(R.string.setup_error_title));
- alertBuilder
- .setMessage(getResources().getString(R.string.setup_error_text))
- .setCancelable(false)
- .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP);
- }
- })
- .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SharedPreferences.Editor prefsEdit = getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE).edit();
- prefsEdit.remove(ConfigHelper.PROVIDER_KEY).commit();
- finish();
- }
- })
- .show();
- }
-
- /**
- * Inflates permanent UI elements of the View and contains logic for what
- * service dependent UI elements to include.
- */
- private void buildDashboard() {
- provider = Provider.getInstance();
- provider.init( this );
-
- setContentView(R.layout.client_dashboard);
-
- providerNameTV = (TextView) findViewById(R.id.providerName);
- providerNameTV.setText(provider.getDomain());
- providerNameTV.setTextSize(28);
-
- FragmentManager fragMan = getFragmentManager();
- if ( provider.hasEIP() && fragMan.findFragmentByTag(TAG_EIP_FRAGMENT) == null){
- EipServiceFragment eipFragment = new EipServiceFragment();
- fragMan.beginTransaction().add(R.id.servicesCollection, eipFragment, TAG_EIP_FRAGMENT).commit();
- }
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- JSONObject provider_json;
- try {
- provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY);
- JSONObject service_description = provider_json.getJSONObject(ConfigHelper.SERVICE_KEY);
- if(service_description.getBoolean(ConfigHelper.ALLOW_REGISTRATION_KEY)) {
- if(authed) {
- menu.findItem(R.id.login_button).setVisible(false);
- menu.findItem(R.id.logout_button).setVisible(true);
- } else {
- menu.findItem(R.id.login_button).setVisible(true);
- menu.findItem(R.id.logout_button).setVisible(false);
- }
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.client_dashboard, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item){
- Intent intent;
- switch (item.getItemId()){
- case R.id.about_leap:
- Fragment aboutFragment = new AboutFragment();
- FragmentTransaction trans = getFragmentManager().beginTransaction();
- trans.replace(R.id.dashboardLayout, aboutFragment);
- trans.addToBackStack(null);
- trans.commit();
- return true;
- case R.id.legacy_interface:
- intent = new Intent(this,MainActivity.class);
- startActivity(intent);
- return true;
- case R.id.switch_provider:
- startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
- return true;
- case R.id.login_button:
- View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(view, "");
- return true;
- case R.id.logout_button:
- logOut();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
-
- }
-
- @Override
- public void authenticate(String username, String password) {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
- method_and_parameters.putString(ConfigHelper.USERNAME_KEY, username);
- method_and_parameters.putString(ConfigHelper.PASSWORD_KEY, password);
-
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(ConfigHelper.PROVIDER_KEY, ""));
- method_and_parameters.putString(ConfigHelper.API_URL_KEY, provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- provider_API_command.putExtra(ConfigHelper.SRP_AUTH, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- if(mProgressDialog != null) mProgressDialog.dismiss();
- mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.authenticating_title), getResources().getString(R.string.authenticating_message), true);
- startService(provider_API_command);
- }
-
- /**
- * Asks ProviderAPI to log out.
- */
- public void logOut() {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
-
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(ConfigHelper.PROVIDER_KEY, ""));
- method_and_parameters.putString(ConfigHelper.API_URL_KEY, provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- provider_API_command.putExtra(ConfigHelper.LOG_OUT, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- if(mProgressDialog != null) mProgressDialog.dismiss();
- mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.logout_title), getResources().getString(R.string.logout_message), true);
- startService(provider_API_command);
- }
-
- /**
- * Shows the log in dialog.
- * @param view from which the dialog is created.
- */
- public void logInDialog(View view, String user_message) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.LOG_IN_DIALOG);
- if (previous_log_in_dialog != null) {
- fragment_transaction.remove(previous_log_in_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = LogInDialog.newInstance();
- if(user_message != null && !user_message.isEmpty()) {
- Bundle user_message_bundle = new Bundle();
- user_message_bundle.putString(getResources().getString(R.string.user_message), user_message);
- newFragment.setArguments(user_message_bundle);
- }
- newFragment.show(fragment_transaction, ConfigHelper.LOG_IN_DIALOG);
- }
-
- /**
- * Asks ProviderAPI to download an authenticated OpenVPN certificate.
- * @param session_id cookie for the server to allow us to download the certificate.
- */
- private void downloadAuthedUserCertificate(Cookie session_id) {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle method_and_parameters = new Bundle();
- method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.AUTHED_CERTIFICATE);
- method_and_parameters.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id.getName());
- method_and_parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue());
-
- provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){
- String session_id_cookie_key = resultData.getString(ConfigHelper.SESSION_ID_COOKIE_KEY);
- String session_id_string = resultData.getString(ConfigHelper.SESSION_ID_KEY);
- setResult(RESULT_OK);
- authed = true;
- invalidateOptionsMenu();
-
- Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string);
- downloadAuthedUserCertificate(session_id);
- } else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) {
- mProgressDialog.dismiss();
- logInDialog(getCurrentFocus(), resultData.getString(getResources().getString(R.string.user_message)));
- } else if(resultCode == ConfigHelper.LOGOUT_SUCCESSFUL) {
- authed = false;
- invalidateOptionsMenu();
- setResult(RESULT_OK);
- mProgressDialog.dismiss();
- } else if(resultCode == ConfigHelper.LOGOUT_FAILED) {
- setResult(RESULT_CANCELED);
- mProgressDialog.dismiss();
- Toast.makeText(getApplicationContext(), R.string.log_out_failed_message, Toast.LENGTH_LONG).show();
- } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- setResult(RESULT_OK);
- mProgressDialog.dismiss();
- Toast.makeText(getApplicationContext(), R.string.successful_authed_cert_downloaded_message, Toast.LENGTH_LONG).show();
- } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- setResult(RESULT_CANCELED);
- mProgressDialog.dismiss();
- Toast.makeText(getApplicationContext(), R.string.authed_cert_download_failed_message, Toast.LENGTH_LONG).show();
- }
- }
-
- /**
- * For retrieving the base application Context in classes that don't extend
- * Android's Activity class
- *
- * @return Application Context as defined by <code>this</code> for Dashboard instance
- */
- public static Context getAppContext() {
- return app;
- }
-
-}
diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java
deleted file mode 100644
index e0685c15..00000000
--- a/src/se/leap/leapclient/EIP.java
+++ /dev/null
@@ -1,511 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Vector;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.openvpn.ConfigParser;
-import se.leap.openvpn.ConfigParser.ConfigParseError;
-import se.leap.openvpn.LaunchVPN;
-import se.leap.openvpn.OpenVpnManagementThread;
-import se.leap.openvpn.OpenVpnService;
-import se.leap.openvpn.OpenVpnService.LocalBinder;
-import se.leap.openvpn.ProfileManager;
-import se.leap.openvpn.VpnProfile;
-
-import android.app.Activity;
-import android.app.IntentService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-/**
- * EIP is the abstract base class for interacting with and managing the Encrypted
- * Internet Proxy connection. Connections are started, stopped, and queried through
- * this IntentService.
- * Contains logic for parsing eip-service.json from the provider, configuring and selecting
- * gateways, and controlling {@link .openvpn.OpenVpnService} connections.
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
-public final class EIP extends IntentService {
-
- public final static String ACTION_START_EIP = "se.leap.leapclient.START_EIP";
- public final static String ACTION_STOP_EIP = "se.leap.leapclient.STOP_EIP";
- public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.leapclient.UPDATE_EIP_SERVICE";
- public final static String ACTION_IS_EIP_RUNNING = "se.leap.leapclient.IS_RUNNING";
- public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION";
-
- private static Context context;
- private static ResultReceiver mReceiver;
- private static OpenVpnService mVpnService;
- private static boolean mBound = false;
- // Used to store actions to "resume" onServiceConnection
- private static String mPending = null;
-
- private static int parsedEipSerial;
- private static JSONObject eipDefinition = null;
-
- private static OVPNGateway activeGateway = null;
-
- public EIP(){
- super("LEAPEIP");
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- context = getApplicationContext();
-
- try {
- eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY);
- parsedEipSerial = ConfigHelper.getIntFromSharedPref(ConfigHelper.EIP_PARSED_SERIAL);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- this.retreiveVpnService();
- }
-
- @Override
- public void onDestroy() {
- unbindService(mVpnServiceConn);
- mBound = false;
-
- super.onDestroy();
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- String action = intent.getAction();
- mReceiver = intent.getParcelableExtra(ConfigHelper.RECEIVER_TAG);
-
- if ( action == ACTION_IS_EIP_RUNNING )
- this.isRunning();
- if ( action == ACTION_UPDATE_EIP_SERVICE )
- this.updateEIPService();
- else if ( action == ACTION_START_EIP )
- this.startEIP();
- else if ( action == ACTION_STOP_EIP )
- this.stopEIP();
- }
-
- /**
- * Sends an Intent to bind OpenVpnService.
- * Used when OpenVpnService isn't bound but might be running.
- */
- private void retreiveVpnService() {
- Intent bindIntent = new Intent(this,OpenVpnService.class);
- bindIntent.setAction(OpenVpnService.RETRIEVE_SERVICE);
- bindService(bindIntent, mVpnServiceConn, 0);
- }
-
- private static ServiceConnection mVpnServiceConn = new ServiceConnection() {
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- LocalBinder binder = (LocalBinder) service;
- mVpnService = binder.getService();
- mBound = true;
-
- if (mReceiver != null && mPending != null) {
-
- boolean running = mVpnService.isRunning();
- int resultCode = Activity.RESULT_CANCELED;
-
- if (mPending.equals(ACTION_IS_EIP_RUNNING))
- resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
- if (mPending.equals(ACTION_START_EIP))
- resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
- else if (mPending.equals(ACTION_STOP_EIP))
- resultCode = (running) ? Activity.RESULT_CANCELED
- : Activity.RESULT_OK;
- Bundle resultData = new Bundle();
- resultData.putString(ConfigHelper.REQUEST_TAG, EIP_NOTIFICATION);
- mReceiver.send(resultCode, resultData);
-
- mPending = null;
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mBound = false;
-
- if (mReceiver != null){
- Bundle resultData = new Bundle();
- resultData.putString(ConfigHelper.REQUEST_TAG, EIP_NOTIFICATION);
- mReceiver.send(Activity.RESULT_CANCELED, resultData);
- }
- }
-
- };
-
- /**
- * Attempts to determine if OpenVpnService has an established VPN connection
- * through the bound ServiceConnection. If there is no bound service, this
- * method will attempt to bind a running OpenVpnService and send
- * <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
- * request.
- * Note: If the request to bind OpenVpnService is successful, the ResultReceiver
- * will be notified in {@link onServiceConnected()}
- */
- private void isRunning() {
- Bundle resultData = new Bundle();
- resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_IS_EIP_RUNNING);
- int resultCode = Activity.RESULT_CANCELED;
- if (mBound) {
- resultCode = (mVpnService.isRunning()) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
- } else {
- mPending = ACTION_IS_EIP_RUNNING;
- this.retreiveVpnService();
- }
-
- if (mReceiver != null){
- mReceiver.send(resultCode, resultData);
- }
- }
-
- /**
- * Initiates an EIP connection by selecting a gateway and preparing and sending an
- * Intent to {@link se.leap.openvpn.LaunchVPN}
- */
- private void startEIP() {
- if (activeGateway==null)
- activeGateway = selectGateway();
-
- Intent intent = new Intent(this,LaunchVPN.class);
- intent.setAction(Intent.ACTION_MAIN);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() );
- intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
- intent.putExtra(ConfigHelper.RECEIVER_TAG, mReceiver);
- startActivity(intent);
- mPending = ACTION_START_EIP;
- }
-
- /**
- * Disconnects the EIP connection gracefully through the bound service or forcefully
- * if there is no bound service. Sends a message to the requesting ResultReceiver.
- */
- private void stopEIP() {
- if (mBound)
- mVpnService.onRevoke();
- else
- OpenVpnManagementThread.stopOpenVPN();
-
- if (mReceiver != null){
- Bundle resultData = new Bundle();
- resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP);
- mReceiver.send(Activity.RESULT_OK, resultData);
- }
- }
-
- /**
- * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()}
- * to parse gateway definitions.
- * TODO Implement API call to refresh eip-service.json from the provider
- */
- private void updateEIPService() {
- try {
- eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if (eipDefinition.optInt("serial") > parsedEipSerial)
- updateGateways();
- }
-
- /**
- * Choose a gateway to connect to based on timezone from system locale data
- *
- * @return The gateway to connect to
- */
- private OVPNGateway selectGateway() {
- // TODO Implement gateway selection logic based on TZ or preferences
- // TODO Implement search through gateways loaded from SharedPreferences
- // TODO Remove String arg constructor in favor of findGatewayByName(String)
- return new OVPNGateway("first");
- }
-
- /**
- * Walk the list of gateways defined in eip-service.json and parse them into
- * OVPNGateway objects.
- * TODO Store the OVPNGateways (as Serializable) in SharedPreferences
- */
- private void updateGateways(){
- JSONArray gatewaysDefined = null;
-
- try {
- gatewaysDefined = eipDefinition.getJSONArray("gateways");
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
-
- JSONObject gw = null;
-
- try {
- gw = gatewaysDefined.getJSONObject(i);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- try {
- if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){
- new OVPNGateway(gw);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- ConfigHelper.saveSharedPref(ConfigHelper.EIP_PARSED_SERIAL, eipDefinition.optInt(ConfigHelper.API_RETURN_SERIAL_KEY));
- }
-
- /**
- * OVPNGateway provides objects defining gateways and their options and metadata.
- * Each instance contains a VpnProfile for OpenVPN specific data and member
- * variables describing capabilities and location
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
- private class OVPNGateway {
-
- private String TAG = "OVPNGateway";
-
- private String mName;
- private VpnProfile mVpnProfile;
- private JSONObject mGateway;
- private HashMap<String,Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
-
-
- /**
- * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it.
- * FIXME This needs to become a findGatewayByName() method
- *
- * @param name The hostname of the gateway to inflate
- */
- private OVPNGateway(String name){
- mName = name;
-
- this.loadVpnProfile();
- }
-
- private void loadVpnProfile() {
- ProfileManager vpl = ProfileManager.getInstance(context);
-
- try {
- if ( mName == "first" ) {
- mName = vpl.getProfiles().iterator().next().mName;
- }
-
- mVpnProfile = vpl.getProfileByName(mName);
-
- } catch (NoSuchElementException e) {
- updateEIPService();
- this.loadVpnProfile(); // FIXME catch infinite loops
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json
- * and create a VpnProfile belonging to it.
- *
- * @param gateway The JSON OpenVPN gateway definition to parse
- */
- protected OVPNGateway(JSONObject gateway){
-
- mGateway = gateway;
-
- // Currently deletes VpnProfile for host, if there already is one, and builds new
- ProfileManager vpl = ProfileManager.getInstance(context);
- Collection<VpnProfile> profiles = vpl.getProfiles();
- for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){
- VpnProfile p = it.next();
- try {
- if ( p.mName.contains( gateway.getString("host") ) )
- it.remove();
- vpl.removeProfile(context, p);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- this.parseOptions();
- this.createVPNProfile();
-
- setUniqueProfileName(vpl);
- vpl.addProfile(mVpnProfile);
- vpl.saveProfile(context, mVpnProfile);
- vpl.saveProfileList(context);
- }
-
- /**
- * Attempts to create a unique profile name from the hostname of the gateway
- *
- * @param profileManager
- */
- private void setUniqueProfileName(ProfileManager profileManager) {
- int i=0;
-
- String newname;
- try {
- newname = mGateway.getString("host");
- while(profileManager.getProfileByName(newname)!=null) {
- i++;
- if(i==1)
- newname = getString(R.string.converted_profile);
- else
- newname = getString(R.string.converted_profile_i,i);
- }
-
- mVpnProfile.mName=newname;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- Log.v(TAG,"Couldn't read gateway name for profile creation!");
- e.printStackTrace();
- }
- }
-
- /**
- * FIXME This method is really the outline of the refactoring needed in se.leap.openvpn.ConfigParser
- */
- private void parseOptions(){
-
- // FIXME move these to a common API (& version) definition place, like ProviderAPI or ConfigHelper
- String common_options = "openvpn_configuration";
- String remote = "ip_address";
- String ports = "ports";
- String protos = "protocols";
- String capabilities = "capabilities";
-
- Vector<String> arg = new Vector<String>();
- Vector<Vector<String>> args = new Vector<Vector<String>>();
-
- try {
- JSONObject def = (JSONObject) eipDefinition.get(common_options);
- Iterator keys = def.keys();
- Vector<Vector<String>> value = new Vector<Vector<String>>();
- while ( keys.hasNext() ){
- String key = keys.next().toString();
-
- arg.add(key);
- for ( String word : def.getString(key).split(" ") )
- arg.add(word);
- value.add( (Vector<String>) arg.clone() );
- options.put(key, (Vector<Vector<String>>) value.clone());
-
- value.clear();
- arg.clear();
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- try {
- arg.add("remote");
- arg.add(mGateway.getString(remote));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- args.add((Vector<String>) arg.clone());
- options.put("remote", (Vector<Vector<String>>) args.clone() );
- arg.clear();
- args.clear();
-
- JSONArray protocolsJSON = null;
- arg.add("proto");
- try {
- protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Vector<String> protocols = new Vector<String>();
- for ( int i=0; i<protocolsJSON.length(); i++ )
- protocols.add(protocolsJSON.optString(i));
- if ( protocols.contains("udp"))
- arg.add("udp");
- else if ( protocols.contains("tcp"))
- arg.add("tcp");
- args.add((Vector<String>) arg.clone());
- options.put("proto", (Vector<Vector<String>>) args.clone());
- arg.clear();
- args.clear();
-
-
- String port = null;
- arg.add("port");
- try {
- port = mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- arg.add(port);
- args.add((Vector<String>) arg.clone());
- options.put("port", (Vector<Vector<String>>) args.clone());
- args.clear();
- arg.clear();
- }
-
- /**
- * Create and attach the VpnProfile to our gateway object
- */
- protected void createVPNProfile(){
- try {
- ConfigParser cp = new ConfigParser();
- cp.setDefinition(options);
- VpnProfile vp = cp.convertProfile();
- mVpnProfile = vp;
- Log.v(TAG,"Created VPNProfile");
- } catch (ConfigParseError e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error createing VPNProfile");
- e.printStackTrace();
- }
- }
- }
-
-}
diff --git a/src/se/leap/leapclient/EipServiceFragment.java b/src/se/leap/leapclient/EipServiceFragment.java
deleted file mode 100644
index c18f83da..00000000
--- a/src/se/leap/leapclient/EipServiceFragment.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package se.leap.leapclient;
-
-import se.leap.openvpn.LogWindow;
-import se.leap.openvpn.OpenVPN;
-import se.leap.openvpn.OpenVPN.StateListener;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.CompoundButton;
-import android.widget.RelativeLayout;
-import android.widget.Switch;
-import android.widget.TextView;
-
-public class EipServiceFragment extends Fragment implements StateListener, OnClickListener, OnCheckedChangeListener {
-
- private static final String IS_EIP_PENDING = "is_eip_pending";
-
- private View eipFragment;
- private Switch eipSwitch;
- private View eipDetail;
- private TextView eipStatus;
-
- private boolean eipAutoSwitched = true;
-
- private boolean mEipStartPending = false;
-
- private EIPReceiver mEIPReceiver;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
- eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false);
-
- eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail));
- eipDetail.setVisibility(View.VISIBLE);
-
- View eipSettings = eipFragment.findViewById(R.id.eipSettings);
- eipSettings.setVisibility(View.GONE); // FIXME too!
-
- if (mEipStartPending)
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
-
- eipStatus = (TextView) eipFragment.findViewById(R.id.eipStatus);
- eipStatus.setOnClickListener(this);
-
- eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch);
- eipSwitch.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- eipAutoSwitched = false;
- return false;
- }
- });
- eipSwitch.setOnCheckedChangeListener(this);
-
- return eipFragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mEIPReceiver = new EIPReceiver(new Handler());
-
- if (savedInstanceState != null)
- mEipStartPending = savedInstanceState.getBoolean(IS_EIP_PENDING);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- OpenVPN.addStateListener(this);
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- OpenVPN.removeStateListener(this);
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(IS_EIP_PENDING, mEipStartPending);
- }
-
- @Override
- public void onClick(View buttonView) {
- if (buttonView.equals(eipStatus))
- showEIPLog();
- }
-
- /**
- * Launches the se.leap.openvpn.LogWindow Activity showing detailed OpenVPN log
- */
- public void showEIPLog(){
- Intent intent = new Intent(getActivity().getBaseContext(),LogWindow.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- startActivity(intent);
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (buttonView.equals(eipSwitch) && !eipAutoSwitched){
- if (isChecked){
- mEipStartPending = true;
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
- ((TextView) eipFragment.findViewById(R.id.eipStatus)).setText(R.string.eip_status_start_pending);
- eipCommand(EIP.ACTION_START_EIP);
- } else {
- if (mEipStartPending){
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
- alertBuilder.setTitle(getResources().getString(R.string.eip_cancel_connect_title));
- alertBuilder
- .setMessage(getResources().getString(R.string.eip_cancel_connect_text))
- .setPositiveButton(getResources().getString(R.string.eip_cancel_connect_cancel), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- eipCommand(EIP.ACTION_STOP_EIP);
- }
- })
- .setNegativeButton(getResources().getString(R.string.eip_cancel_connect_false), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- eipAutoSwitched = true;
- eipSwitch.setChecked(true);
- eipAutoSwitched = false;
- }
- })
- .show();
- } else {
- eipCommand(EIP.ACTION_STOP_EIP);
- }
- }
- }
- eipAutoSwitched = true;
- }
-
- /**
- * 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 vpnIntent = new Intent(action);
- vpnIntent.putExtra(ConfigHelper.RECEIVER_TAG, mEIPReceiver);
- getActivity().startService(vpnIntent);
- }
-
- @Override
- public void updateState(final String state, final String logmessage, final int localizedResId) {
- // Note: "states" are not organized anywhere...collected state strings:
- // NOPROCESS,NONETWORK,BYTECOUNT,AUTH_FAILED + some parsing thing ( WAIT(?),AUTH,GET_CONFIG,ASSIGN_IP,CONNECTED,SIGINT )
- getActivity().runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- if (eipStatus != null) {
- boolean switchState = true;
- String statusMessage = "";
- String prefix = getString(localizedResId);
- if (state.equals("CONNECTED")){
- statusMessage = "Connection Secure";
- getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
- mEipStartPending = false;
- } else if (state.equals("BYTECOUNT")) {
- statusMessage = logmessage;
- } else if ( (state.equals("NOPROCESS") && !mEipStartPending ) || state.equals("EXITING")) {
- statusMessage = "Not running! Connection not secure!";
- getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
- mEipStartPending = false;
- switchState = false;
- } else {
- statusMessage = prefix + logmessage;
- }
-
- eipAutoSwitched = true;
- eipSwitch.setChecked(switchState);
- eipAutoSwitched = false;
- eipStatus.setText(statusMessage);
- }
- }
- });
- }
-
- /**
- * Inner class for handling messages related to EIP status and control requests
- *
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- */
- 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(ConfigHelper.REQUEST_TAG);
- boolean checked = false;
-
- if (request == EIP.ACTION_IS_EIP_RUNNING) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = true;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- break;
- }
- } else if (request == EIP.ACTION_START_EIP) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = true;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE);
- break;
- }
- } else if (request == EIP.ACTION_STOP_EIP) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = false;
- break;
- case Activity.RESULT_CANCELED:
- checked = true;
- break;
- }
- } else if (request == EIP.EIP_NOTIFICATION) {
- switch (resultCode){
- case Activity.RESULT_OK:
- checked = true;
- break;
- case Activity.RESULT_CANCELED:
- checked = false;
- break;
- }
- }
-
- eipAutoSwitched = true;
- eipSwitch.setChecked(checked);
- eipAutoSwitched = false;
- }
- }
-}
diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java
deleted file mode 100644
index 686d3cc0..00000000
--- a/src/se/leap/leapclient/LeapHttpClient.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.security.KeyStore;
-
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.SingleClientConnManager;
-import android.content.Context;
-
-/**
- * Implements an HTTP client, enabling LEAP Android app to manage its own runtime keystore or bypass default Android security measures.
- *
- * @author rafa
- *
- */
-public class LeapHttpClient extends DefaultHttpClient {
- final Context context;
-
- private static LeapHttpClient client;
-
- /**
- * If the class scope client is null, it creates one and imports, if existing, the main certificate from Shared Preferences.
- * @param context
- * @return the new client.
- */
- public static LeapHttpClient getInstance(Context context) {
- if(client == null) {
- client = new LeapHttpClient(context);
- String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY);
- if(cert_string != null) {
- ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string);
- }
- }
- return client;
- }
-
- @Override
- protected ClientConnectionManager createClientConnectionManager() {
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", newSslSocketFactory(), 443));
-
- return new SingleClientConnManager(getParams(), registry);
- }
-
- /**
- * Uses keystore from ConfigHelper for the SSLSocketFactory.
- *
- * Sets hostname verifier to allow all hostname verifier.
- * @return
- */
- private SSLSocketFactory newSslSocketFactory() {
- try {
- KeyStore trusted = ConfigHelper.getKeystore();
- SSLSocketFactory sf = new SSLSocketFactory(trusted);
- sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-
- return sf;
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public LeapHttpClient(Context context) {
- this.context = context;
- }
-}
diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java
deleted file mode 100644
index 9451c1be..00000000
--- a/src/se/leap/leapclient/LeapSRPSession.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-
-import org.jboss.security.srp.SRPParameters;
-
-/**
- * Implements all SRP algorithm logic.
- *
- * It's derived from JBoss implementation, with adjustments to make it work with LEAP platform.
- *
- * @author parmegv
- *
- */
-public class LeapSRPSession {
-
- private SRPParameters params;
- private String username;
- private String password;
- private BigInteger N;
- private byte[] N_bytes;
- private BigInteger g;
- private BigInteger x;
- private BigInteger v;
- private BigInteger a;
- private BigInteger A;
- private byte[] K;
- private SecureRandom pseudoRng;
- /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */
- private MessageDigest clientHash;
- /** The M2 = H(A | M | K) hash */
- private MessageDigest serverHash;
-
- private static int A_LEN;
-
- /** Creates a new SRP server session object from the username, password
- verifier,
- @param username, the user ID
- @param password, the user clear text password
- @param params, the SRP parameters for the session
- */
- public LeapSRPSession(String username, String password, SRPParameters params)
- {
- this(username, password, params, null);
- }
-
- /** Creates a new SRP server session object from the username, password
- verifier,
- @param username, the user ID
- @param password, the user clear text password
- @param params, the SRP parameters for the session
- @param abytes, the random exponent used in the A public key
- */
- public LeapSRPSession(String username, String password, SRPParameters params,
- byte[] abytes) {
- this.params = params;
- this.g = new BigInteger(1, params.g);
- N_bytes = ConfigHelper.trim(params.N);
- this.N = new BigInteger(1, N_bytes);
- this.username = username;
- this.password = password;
-
- try {
- pseudoRng = SecureRandom.getInstance("SHA1PRNG");
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if( abytes != null ) {
- A_LEN = 8*abytes.length;
- /* TODO Why did they put this condition?
- if( 8*abytes.length != A_LEN )
- throw new IllegalArgumentException("The abytes param must be "
- +(A_LEN/8)+" in length, abytes.length="+abytes.length);
- */
- this.a = new BigInteger(abytes);
- }
- else
- A_LEN = 64;
-
- serverHash = newDigest();
- clientHash = newDigest();
- }
-
- /**
- * Calculates the parameter x of the SRP-6a algorithm.
- * @param username
- * @param password
- * @param salt the salt of the user
- * @return x
- */
- public byte[] calculatePasswordHash(String username, String password, byte[] salt)
- {
- //password = password.replaceAll("\\\\", "\\\\\\\\");
- // Calculate x = H(s | H(U | ':' | password))
- MessageDigest x_digest = newDigest();
- // Try to convert the username to a byte[] using ISO-8859-1
- byte[] user = null;
- byte[] password_bytes = null;
- byte[] colon = {};
- String encoding = "ISO-8859-1";
- try {
- user = ConfigHelper.trim(username.getBytes(encoding));
- colon = ConfigHelper.trim(":".getBytes(encoding));
- password_bytes = ConfigHelper.trim(password.getBytes(encoding));
- }
- catch(UnsupportedEncodingException e) {
- // Use the default platform encoding
- user = ConfigHelper.trim(username.getBytes());
- colon = ConfigHelper.trim(":".getBytes());
- password_bytes = ConfigHelper.trim(password.getBytes());
- }
-
- // Build the hash
- x_digest.update(user);
- x_digest.update(colon);
- x_digest.update(password_bytes);
- byte[] h = x_digest.digest();
-
- x_digest.reset();
- x_digest.update(salt);
- x_digest.update(h);
- byte[] x_digest_bytes = x_digest.digest();
-
- return x_digest_bytes;
- }
-
- /**
- * Calculates the parameter V of the SRP-6a algorithm.
- * @param k_string constant k predefined by the SRP server implementation.
- * @return the value of V
- */
- private BigInteger calculateV(String k_string) {
- BigInteger k = new BigInteger(k_string, 16);
- BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N
- return v;
- }
-
- /**
- * Calculates the trimmed xor from two BigInteger numbers
- * @param b1 the positive source to build first BigInteger
- * @param b2 the positive source to build second BigInteger
- * @param length
- * @return
- */
- public byte[] xor(byte[] b1, byte[] b2)
- {
- //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa
- byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray();
- return ConfigHelper.trim(xor_digest);
- }
-
- /**
- * @returns The exponential residue (parameter A) to be sent to the server.
- */
- public byte[] exponential() {
- byte[] Abytes = null;
- if(A == null) {
- /* If the random component of A has not been specified use a random
- number */
- if( a == null ) {
- BigInteger one = BigInteger.ONE;
- do {
- a = new BigInteger(A_LEN, pseudoRng);
- } while(a.compareTo(one) <= 0);
- }
- A = g.modPow(a, N);
- Abytes = ConfigHelper.trim(A.toByteArray());
- }
- return Abytes;
- }
-
- /**
- * Calculates the parameter M1, to be sent to the SRP server.
- * It also updates hashes of client and server for further calculations in other methods.
- * It uses a predefined k.
- * @param salt_bytes
- * @param Bbytes the parameter received from the server, in bytes
- * @return the parameter M1
- * @throws NoSuchAlgorithmException
- */
- public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException {
- // Calculate x = H(s | H(U | ':' | password))
- byte[] xb = calculatePasswordHash(username, password, ConfigHelper.trim(salt_bytes));
- this.x = new BigInteger(1, xb);
-
- // Calculate v = kg^x mod N
- String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0";
- this.v = calculateV(k_string);
-
- // H(N)
- byte[] digest_of_n = newDigest().digest(N_bytes);
-
- // H(g)
- byte[] digest_of_g = newDigest().digest(params.g);
-
- // clientHash = H(N) xor H(g)
- byte[] xor_digest = xor(digest_of_n, digest_of_g);
- clientHash.update(xor_digest);
-
- // clientHash = H(N) xor H(g) | H(U)
- byte[] username_digest = newDigest().digest(ConfigHelper.trim(username.getBytes()));
- username_digest = ConfigHelper.trim(username_digest);
- clientHash.update(username_digest);
-
- // clientHash = H(N) xor H(g) | H(U) | s
- clientHash.update(ConfigHelper.trim(salt_bytes));
-
- K = null;
-
- // clientHash = H(N) xor H(g) | H(U) | A
- byte[] Abytes = ConfigHelper.trim(A.toByteArray());
- clientHash.update(Abytes);
-
- // clientHash = H(N) xor H(g) | H(U) | s | A | B
- Bbytes = ConfigHelper.trim(Bbytes);
- clientHash.update(Bbytes);
-
- // Calculate S = (B - kg^x) ^ (a + u * x) % N
- BigInteger S = calculateS(Bbytes);
- byte[] S_bytes = ConfigHelper.trim(S.toByteArray());
-
- // K = SessionHash(S)
- String hash_algorithm = params.hashAlgorithm;
- MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm);
- K = ConfigHelper.trim(sessionDigest.digest(S_bytes));
-
- // clientHash = H(N) xor H(g) | H(U) | A | B | K
- clientHash.update(K);
-
- byte[] M1 = ConfigHelper.trim(clientHash.digest());
-
- // serverHash = Astr + M + K
- serverHash.update(Abytes);
- serverHash.update(M1);
- serverHash.update(K);
-
- return M1;
- }
-
- /**
- * It calculates the parameter S used by response() to obtain session hash K.
- * @param Bbytes the parameter received from the server, in bytes
- * @return the parameter S
- */
- private BigInteger calculateS(byte[] Bbytes) {
- byte[] Abytes = ConfigHelper.trim(A.toByteArray());
- Bbytes = ConfigHelper.trim(Bbytes);
- byte[] u_bytes = getU(Abytes, Bbytes);
-
- BigInteger B = new BigInteger(1, Bbytes);
- BigInteger u = new BigInteger(1, u_bytes);
-
- BigInteger B_minus_v = B.subtract(v);
- BigInteger a_ux = a.add(u.multiply(x));
- BigInteger S = B_minus_v.modPow(a_ux, N);
- return S;
- }
-
- /**
- * It calculates the parameter u used by calculateS to obtain S.
- * @param Abytes the exponential residue sent to the server
- * @param Bbytes the parameter received from the server, in bytes
- * @return
- */
- public byte[] getU(byte[] Abytes, byte[] Bbytes) {
- MessageDigest u_digest = newDigest();
- u_digest.update(ConfigHelper.trim(Abytes));
- u_digest.update(ConfigHelper.trim(Bbytes));
- byte[] u_digest_bytes = u_digest.digest();
- return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray());
- }
-
- /**
- * @param M2 The server's response to the client's challenge
- * @returns True if and only if the server's response was correct.
- */
- public boolean verify(byte[] M2)
- {
- // M2 = H(A | M1 | K)
- M2 = ConfigHelper.trim(M2);
- byte[] myM2 = ConfigHelper.trim(serverHash.digest());
- boolean valid = Arrays.equals(M2, myM2);
- return valid;
- }
-
- /**
- * @return a new SHA-256 digest.
- */
- public MessageDigest newDigest()
- {
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return md;
- }
-}
diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java
deleted file mode 100644
index 8b3f9e80..00000000
--- a/src/se/leap/leapclient/LogInDialog.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import se.leap.leapclient.R;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
-
-/**
- * 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 LogInDialog extends DialogFragment {
-
- public AlertDialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null);
-
- final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message);
- if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) {
- user_message.setText(getArguments().getString(getResources().getString(R.string.user_message)));
- } else user_message.setVisibility(View.GONE);
- final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered);
- final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered);
-
- builder.setView(log_in_dialog_view)
- .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = username_field.getText().toString().trim();
- String password = password_field.getText().toString().trim();
- interface_with_Dashboard.authenticate(username, password);
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
-
- return builder.create();
- }
-
- /**
- * Interface used to communicate LogInDialog with Dashboard.
- *
- * @author parmegv
- *
- */
- public interface LogInDialogInterface {
- /**
- * Starts authentication process.
- * @param username
- * @param password
- */
- public void authenticate(String username, String password);
- }
-
- LogInDialogInterface interface_with_Dashboard;
-
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance() {
- LogInDialog dialog_fragment = new LogInDialog();
- return dialog_fragment;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- interface_with_Dashboard = (LogInDialogInterface) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement LogInDialogListener");
- }
- }
-}
diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java
deleted file mode 100644
index 0b9d8fd0..00000000
--- a/src/se/leap/leapclient/NewProviderDialog.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import se.leap.leapclient.R;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.Toast;
-
-/**
- * Implements the new custom provider dialog.
- *
- * @author parmegv
- *
- */
-public class NewProviderDialog extends DialogFragment {
-
- public interface NewProviderDialogInterface {
- public void saveAndSelectProvider(String url_provider, boolean danger_on);
- }
-
- NewProviderDialogInterface interface_with_ConfigurationWizard;
-
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance() {
- NewProviderDialog dialog_fragment = new NewProviderDialog();
- return dialog_fragment;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement NoticeDialogListener");
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View new_provider_dialog_view = inflater.inflate(R.layout.new_provider_dialog, null);
- final EditText url_input_field = (EditText)new_provider_dialog_view.findViewById(R.id.new_provider_url);
- final CheckBox danger_checkbox = (CheckBox)new_provider_dialog_view.findViewById(R.id.danger_checkbox);
-
- builder.setView(new_provider_dialog_view)
- .setMessage(R.string.introduce_new_provider)
- .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String entered_url = url_input_field.getText().toString().trim();
- if(!entered_url.startsWith("https://")) {
- entered_url = "https://".concat(entered_url);
- }
- boolean danger_on = danger_checkbox.isChecked();
- if(validURL(entered_url)) {
- interface_with_ConfigurationWizard.saveAndSelectProvider(entered_url, danger_on);
- Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();
- } else {
- url_input_field.setText("");
- Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();
- }
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
- // Create the AlertDialog object and return it
- return builder.create();
- }
-
- /**
- * Checks if the entered url is valid or not.
- * @param entered_url
- * @return true if it's not empty nor contains only the protocol.
- */
- boolean validURL(String entered_url) {
- return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty();
- }
-}
diff --git a/src/se/leap/leapclient/Provider.java b/src/se/leap/leapclient/Provider.java
deleted file mode 100644
index cdcd56c5..00000000
--- a/src/se/leap/leapclient/Provider.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package se.leap.leapclient;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Locale;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.Context;
-import android.app.Activity;
-import android.content.SharedPreferences;
-
-/**
- * @author Sean Leonard <meanderingcode@aetherislands.net>
- *
- */
-public final class Provider implements Serializable {
-
- private static final long serialVersionUID = 6003835972151761353L;
-
- private static Provider instance = null;
-
- // We'll access our preferences here
- private static SharedPreferences preferences = null;
- // Represents our Provider's provider.json
- private static JSONObject definition = null;
-
-
- // Array of what API versions we understand
- protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers"
- // Some API pieces we want to know about
- private static final String API_TERM_SERVICES = "services";
- private static final String API_TERM_NAME = "name";
- private static final String API_TERM_DOMAIN = "domain";
- private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
- protected static final String[] API_EIP_TYPES = {"openvpn"};
-
- private static final String PREFS_EIP_NAME = null;
-
-
-
- // What, no individual fields?! We're going to gamble on org.json.JSONObject and JSONArray
- // Supporting multiple API versions will probably break this paradigm,
- // Forcing me to write a real constructor and rewrite getters/setters
- // Also will refactor if i'm instantiating the same local variables all the time
-
- /**
- *
- */
- private Provider() {}
-
- protected static Provider getInstance(){
- if(instance==null){
- instance = new Provider();
- }
- return instance;
- }
-
- protected void init(Activity activity) {
-
- // Load our preferences from SharedPreferences
- // If there's nothing there, we will end up returning a rather empty object
- // to whoever called getInstance() and they can run the First Run Wizard
- //preferences = context.getgetPreferences(0); // 0 == MODE_PRIVATE, but we don't extend Android's classes...
-
- // Load SharedPreferences
- preferences = activity.getSharedPreferences(ConfigHelper.PREFERENCES_KEY,Context.MODE_PRIVATE);
- // Inflate our provider.json data
- try {
- definition = new JSONObject( preferences.getString("provider", "") );
- } catch (JSONException e) {
- // TODO: handle exception
-
- // FIXME!! We want "real" data!!
- }
- }
-
- protected String getDomain(){
- String domain = "Null";
- try {
- domain = definition.getString(API_TERM_DOMAIN);
- } catch (JSONException e) {
- domain = "Null";
- e.printStackTrace();
- }
- return domain;
- }
-
- protected String getName(){
- // Should we pass the locale in, or query the system here?
- String lang = Locale.getDefault().getLanguage();
- String name = "Null"; // Should it actually /be/ null, for error conditions?
- try {
- name = definition.getJSONObject(API_TERM_NAME).getString(lang);
- } catch (JSONException e) {
- // TODO: Nesting try/catch blocks? Crazy
- // Maybe you should actually handle exception?
- try {
- name = definition.getJSONObject(API_TERM_NAME).getString( definition.getString(API_TERM_DEFAULT_LANGUAGE) );
- } catch (JSONException e2) {
- // TODO: Will you handle the exception already?
- }
- }
-
- return name;
- }
-
- protected String getDescription(){
- String lang = Locale.getDefault().getLanguage();
- String desc = null;
- try {
- desc = definition.getJSONObject("description").getString(lang);
- } catch (JSONException e) {
- // TODO: handle exception!!
- try {
- desc = definition.getJSONObject("description").getString( definition.getString("default_language") );
- } catch (JSONException e2) {
- // TODO: i can't believe you're doing it again!
- }
- }
-
- return desc;
- }
-
- protected boolean hasEIP() {
- JSONArray services = null;
- try {
- services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"]
- } catch (Exception e) {
- // TODO: handle exception
- }
- for (int i=0;i<API_EIP_TYPES.length+1;i++){
- try {
- // Walk the EIP types array looking for matches in provider's service definitions
- if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) )
- return true;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return false;
- }
-
- protected String getEIPType() {
- // FIXME!!!!! We won't always be providing /only/ OpenVPN, will we?
- // This will have to hook into some saved choice of EIP transport
- if ( instance.hasEIP() )
- return "OpenVPN";
- else
- return null;
- }
-
- protected JSONObject getEIP() {
- // FIXME!!!!! We won't always be providing /only/ OpenVPN, will we?
- // This will have to hook into some saved choice of EIP transport, cluster, gateway
- // with possible "choose at random" preference
- if ( instance.hasEIP() ){
- // TODO Might need an EIP class, but we've only got OpenVPN type right now,
- // and only one gateway for our only provider...
- // TODO We'll try to load from preferences, have to call ProviderAPI if we've got nothin...
- JSONObject eipObject = null;
- try {
- eipObject = new JSONObject( preferences.getString(PREFS_EIP_NAME, "") );
- } catch (JSONException e) {
- // TODO ConfigHelper.rescueJSON()
- // Still nothing?
- // TODO ProviderAPI.getEIP()
- e.printStackTrace();
- }
-
- return eipObject;
- } else
- return null;
- }
-}
diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java
deleted file mode 100644
index 944a0e7f..00000000
--- a/src/se/leap/leapclient/ProviderAPI.java
+++ /dev/null
@@ -1,733 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.SecureRandom;
-import javax.net.ssl.KeyManager;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.HttpCookie;
-import java.net.MalformedURLException;
-import java.net.SocketTimeoutException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.UnknownHostException;
-import java.util.Scanner;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.cookie.Cookie;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
-import org.jboss.security.srp.SRPParameters;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import se.leap.leapclient.ProviderListContent.ProviderItem;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.util.Base64;
-import android.util.Log;
-import android.widget.Toast;
-
-/**
- * Implements HTTP api methods used to manage communications with the provider server.
- *
- * It's an IntentService because it downloads data from the Internet, so it operates in the background.
- *
- * @author parmegv
- * @author MeanderingCode
- *
- */
-public class ProviderAPI extends IntentService {
-
- private Handler mHandler;
-
- public ProviderAPI() {
- super("ProviderAPI");
- Log.v("ClassName", "Provider API");
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mHandler = new Handler();
- }
-
- private void displayToast(final int toast_string_id) {
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- Toast.makeText(ProviderAPI.this, toast_string_id, Toast.LENGTH_LONG).show();
- }
- });
- }
-
- @Override
- protected void onHandleIntent(Intent task_for) {
- final ResultReceiver receiver = task_for.getParcelableExtra("receiver");
-
- Bundle task;
- if((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA)) != null) {
- if(!downloadJsonFiles(task)) {
- receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);
- } else {
- receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);
- }
- }
- else if ((task = task_for.getBundleExtra(ConfigHelper.UPDATE_PROVIDER_DOTJSON)) != null) {
- Bundle result = updateProviderDotJSON(task);
- if(result.getBoolean(ConfigHelper.RESULT_KEY)) {
- receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result);
- } else {
- receiver.send(ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON, Bundle.EMPTY);
- }
- }
- else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_NEW_PROVIDER_DOTJSON)) != null) {
- Bundle result = downloadNewProviderDotJSON(task);
- if(result.getBoolean(ConfigHelper.RESULT_KEY)) {
- receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result);
- } else {
- receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);
- }
- }
- else if ((task = task_for.getBundleExtra(ConfigHelper.SRP_AUTH)) != null) {
- Bundle session_id_bundle = authenticateBySRP(task);
- if(session_id_bundle.getBoolean(ConfigHelper.RESULT_KEY)) {
- receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle);
- } else {
- Bundle user_message_bundle = new Bundle();
- String user_message_key = getResources().getString(R.string.user_message);
- user_message_bundle.putString(user_message_key, session_id_bundle.getString(user_message_key));
- receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, user_message_bundle);
- }
- }
- else if ((task = task_for.getBundleExtra(ConfigHelper.LOG_OUT)) != null) {
- if(logOut(task)) {
- receiver.send(ConfigHelper.LOGOUT_SUCCESSFUL, Bundle.EMPTY);
- } else {
- receiver.send(ConfigHelper.LOGOUT_FAILED, Bundle.EMPTY);
- }
- }
- else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_CERTIFICATE)) != null) {
- if(getNewCert(task)) {
- receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
- } else {
- receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
- }
- }
- }
-
- /**
- * Downloads the main cert and the eip-service.json files given through the task parameter
- * @param task
- * @return true if eip-service.json was parsed as a JSON object correctly.
- */
- private boolean downloadJsonFiles(Bundle task) {
- String cert_url = task.getString(ConfigHelper.MAIN_CERT_KEY);
- String eip_service_json_url = task.getString(ConfigHelper.EIP_SERVICE_KEY);
- boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON);
- try {
- String cert_string = getStringFromProvider(cert_url, danger_on);
- ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_string);
- JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url, danger_on);
- ConfigHelper.saveSharedPref(ConfigHelper.EIP_SERVICE_KEY, eip_service_json);
- return true;
- } catch (JSONException e) {
- return false;
- }
- }
-
- /**
- * Starts the authentication process using SRP protocol.
- *
- * @param task containing: username, password and api url.
- * @return a bundle with a boolean value mapped to a key named ConfigHelper.RESULT_KEY, and which is true if authentication was successful.
- */
- private Bundle authenticateBySRP(Bundle task) {
- Bundle session_id_bundle = new Bundle();
-
- String username = (String) task.get(ConfigHelper.USERNAME_KEY);
- String password = (String) task.get(ConfigHelper.PASSWORD_KEY);
- if(wellFormedPassword(password)) {
- String authentication_server = (String) task.get(ConfigHelper.API_URL_KEY);
-
- SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256");
- LeapSRPSession client = new LeapSRPSession(username, password, params);
- byte[] A = client.exponential();
- try {
- JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16));
- if(saltAndB.length() > 0) {
- String salt = saltAndB.getString(ConfigHelper.SALT_KEY);
- byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray();
- byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes);
- JSONObject session_idAndM2 = sendM1ToSRPServer(authentication_server, username, M1);
- if(session_idAndM2.has("M2") && client.verify((byte[])session_idAndM2.get("M2"))) {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, true);
- session_id_bundle.putString(ConfigHelper.SESSION_ID_KEY, session_idAndM2.getString(ConfigHelper.SESSION_ID_KEY));
- session_id_bundle.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_idAndM2.getString(ConfigHelper.SESSION_ID_COOKIE_KEY));
- } else {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_bad_user_password_user_message));
- }
- } else {
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_bad_user_password_user_message));
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- }
- } catch (ClientProtocolException e) {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_client_http_user_message));
- } catch (IOException e) {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_io_exception_user_message));
- } catch (JSONException e) {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_json_exception_user_message));
- } catch (NoSuchAlgorithmException e) {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_no_such_algorithm_exception_user_message));
- }
- } else {
- session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false);
- session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_not_valid_password_user_message));
- }
-
- return session_id_bundle;
- }
-
- /**
- * Validates a password
- * @param entered_password
- * @return true if the entered password length is greater or equal to eight (8).
- */
- private boolean wellFormedPassword(String entered_password) {
- return entered_password.length() >= 8;
- }
-
- /**
- * Sends an HTTP POST request to the authentication server with the SRP Parameter A.
- * @param server_url
- * @param username
- * @param clientA First SRP parameter sent
- * @return response from authentication server
- * @throws ClientProtocolException
- * @throws IOException
- * @throws JSONException
- */
- private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException {
- HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + "login=" + username + "&&" + "A=" + clientA);
- return sendToServer(post);
- }
-
- /**
- * Sends an HTTP PUT request to the authentication server with the SRP Parameter M1 (or simply M).
- * @param server_url
- * @param username
- * @param m1 Second SRP parameter sent
- * @return response from authentication server
- * @throws ClientProtocolException
- * @throws IOException
- * @throws JSONException
- */
- private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException {
- HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, ConfigHelper.trim(m1)).toString(16));
- JSONObject json_response = sendToServer(put);
-
- JSONObject session_idAndM2 = new JSONObject();
- if(json_response.length() > 0) {
- byte[] M2_not_trimmed = new BigInteger(json_response.getString(ConfigHelper.M2_KEY), 16).toByteArray();
- Cookie session_id_cookie = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies().get(0);
- session_idAndM2.put(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id_cookie.getName());
- session_idAndM2.put(ConfigHelper.SESSION_ID_KEY, session_id_cookie.getValue());
- session_idAndM2.put(ConfigHelper.M2_KEY, ConfigHelper.trim(M2_not_trimmed));
- }
- return session_idAndM2;
- }
-
- /**
- * Executes an HTTP request expecting a JSON response.
- * @param request
- * @return response from authentication server
- * @throws ClientProtocolException
- * @throws IOException
- * @throws JSONException
- */
- private JSONObject sendToServer(HttpUriRequest request) throws ClientProtocolException, IOException, JSONException {
- DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext());
- HttpContext localContext = new BasicHttpContext();
- localContext.setAttribute(ClientContext.COOKIE_STORE, client.getCookieStore());
-
- HttpResponse getResponse = client.execute(request, localContext);
- HttpEntity responseEntity = getResponse.getEntity();
- String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next();
- JSONObject json_response = new JSONObject(plain_response);
- if(!json_response.isNull(ConfigHelper.ERRORS_KEY) || json_response.has(ConfigHelper.ERRORS_KEY)) {
- return new JSONObject();
- }
-
- return json_response;
- }
-
- /**
- * Downloads a provider.json from a given URL, adding a new provider using the given name.
- * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url.
- * @return a bundle with a boolean value mapped to a key named ConfigHelper.RESULT_KEY, and which is true if the update was successful.
- */
- private Bundle updateProviderDotJSON(Bundle task) {
- Bundle result = new Bundle();
- boolean custom = task.getBoolean(ConfigHelper.CUSTOM);
- boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON);
- String provider_json_url = task.getString(ConfigHelper.PROVIDER_JSON_URL);
- String provider_name = task.getString(ConfigHelper.PROVIDER_NAME);
-
- try {
- JSONObject provider_json = getJSONFromProvider(provider_json_url, danger_on);
- if(provider_json == null) {
- result.putBoolean(ConfigHelper.RESULT_KEY, false);
- } else {
- ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
-
- //ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on));
- result.putBoolean(ConfigHelper.RESULT_KEY, true);
- result.putString(ConfigHelper.PROVIDER_KEY, provider_json.toString());
- result.putBoolean(ConfigHelper.DANGER_ON, danger_on);
- }
- } catch (JSONException e) {
- result.putBoolean(ConfigHelper.RESULT_KEY, false);
- }
-
- return result;
- }
-
- /**
- * Downloads a custom provider provider.json file
- * @param task containing a boolean meaning if the user completely trusts this provider, and the provider main url entered in the new custom provider dialog.
- * @return true if provider.json file was successfully parsed as a JSON object.
- */
- private Bundle downloadNewProviderDotJSON(Bundle task) {
- Bundle result = new Bundle();
- boolean custom = true;
- boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON);
-
- String provider_main_url = (String) task.get(ConfigHelper.PROVIDER_MAIN_URL);
- String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
- String provider_json_url = guessProviderDotJsonURL(provider_main_url);
-
- JSONObject provider_json;
- try {
- provider_json = getJSONFromProvider(provider_json_url, danger_on);
- if(provider_json == null) {
- result.putBoolean(ConfigHelper.RESULT_KEY, false);
- } else {
-
- ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json);
- ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on);
- ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
- ProviderItem added_provider = new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on);
- ProviderListContent.addItem(added_provider);
-
- result.putString(ConfigHelper.PROVIDER_ID, added_provider.getId());
- result.putBoolean(ConfigHelper.RESULT_KEY, true);
- result.putString(ConfigHelper.PROVIDER_KEY, provider_json.toString());
- result.putBoolean(ConfigHelper.DANGER_ON, danger_on);
- }
- } catch (JSONException e) {
- result.putBoolean(ConfigHelper.RESULT_KEY, false);
- }
-
- return result;
- }
-
- /**
- * Tries to download whatever is pointed by the string_url.
- *
- * If danger_on flag is true, SSL exceptions will be managed by futher methods that will try to use some bypass methods.
- * @param string_url
- * @param danger_on if the user completely trusts this provider
- * @return
- */
- private String getStringFromProvider(String string_url, boolean danger_on) {
-
- String json_file_content = "";
-
- URL provider_url = null;
- int seconds_of_timeout = 1;
- try {
- provider_url = new URL(string_url);
- URLConnection url_connection = provider_url.openConnection();
- url_connection.setConnectTimeout(seconds_of_timeout*1000);
- json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next();
- } catch (MalformedURLException e) {
- displayToast(R.string.malformed_url);
- } catch(SocketTimeoutException e) {
- displayToast(R.string.server_is_down_message);
- } catch (IOException e) {
- if(provider_url != null) {
- json_file_content = getStringFromProviderWithCACertAdded(provider_url, danger_on);
- } else {
- displayToast(R.string.certificate_error);
- }
- } catch (Exception e) {
- if(provider_url != null && danger_on) {
- json_file_content = getStringFromProviderWithCACertAdded(provider_url, danger_on);
- }
- }
-
- return json_file_content;
- }
-
- /**
- * Tries to download a string from given url without verifying the hostname.
- *
- * If a IOException still occurs, it tries with another bypass method: getStringFromProviderWithCACertAdded.
- * @param string_url
- * @return an empty string if everything fails, the url content if not.
- */
- private String getStringFromProviderWithoutValidate(
- URL string_url) {
-
- String json_string = "";
- HostnameVerifier hostnameVerifier = new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- return true;
- }
- };
-
- try {
- HttpsURLConnection urlConnection =
- (HttpsURLConnection)string_url.openConnection();
- urlConnection.setHostnameVerifier(hostnameVerifier);
- json_string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
- } catch (MalformedURLException e) {
- displayToast(R.string.malformed_url);
- } catch (IOException e) {
- json_string = getStringFromProviderIgnoringCertificate(string_url);
- }
-
- return json_string;
- }
-
- /**
- * Tries to download the contents of the provided url using main certificate from choosen provider.
- * @param url
- * @param danger_on true to download CA certificate in case it has not been downloaded.
- * @return an empty string if it fails, the url content if not.
- */
- private String getStringFromProviderWithCACertAdded(URL url, boolean danger_on) {
- String json_file_content = "";
-
- // Load CAs from an InputStream
- // (could be from a resource or ByteArrayInputStream or ...)
- String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY);
- if(cert_string.isEmpty() && danger_on) {
- cert_string = downloadCertificateWithoutTrusting(url.getProtocol() + "://" + url.getHost() + "/" + "ca.crt");
- ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_string);
- }
-
- try {
- java.security.cert.Certificate dangerous_certificate = ConfigHelper.parseX509CertificateFromString(cert_string);
-
- // Create a KeyStore containing our trusted CAs
- String keyStoreType = KeyStore.getDefaultType();
- KeyStore keyStore = KeyStore.getInstance(keyStoreType);
- keyStore.load(null, null);
- keyStore.setCertificateEntry("provider_ca_certificate", dangerous_certificate);
-
- // Create a TrustManager that trusts the CAs in our KeyStore
- String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
- tmf.init(keyStore);
-
- // Create an SSLContext that uses our TrustManager
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, tmf.getTrustManagers(), null);
-
- // Tell the URLConnection to use a SocketFactory from our SSLContext
- HttpsURLConnection urlConnection =
- (HttpsURLConnection)url.openConnection();
- urlConnection.setSSLSocketFactory(context.getSocketFactory());
- json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (UnknownHostException e) {
- displayToast(R.string.server_is_down_message);
- } catch (IOException e) {
- // The downloaded certificate doesn't validate our https connection.
- if(danger_on) {
- json_file_content = getStringFromProviderWithoutValidate(url);
- } else {
- displayToast(R.string.certificate_error);
- }
- } catch (KeyStoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (KeyManagementException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return json_file_content;
- }
-
- /**
- * Downloads the string that's in the url without regarding certificate validity
- */
- private String getStringFromProviderIgnoringCertificate(URL url) {
- String string = "";
- try {
- class DefaultTrustManager implements X509TrustManager {
-
- @Override
- public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
-
- @Override
- public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- }
-
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
-
- HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
- urlConnection.setSSLSocketFactory(context.getSocketFactory());
- urlConnection.setHostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(String arg0, SSLSession arg1) {
- return true;
- }
- });
- string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
- System.out.println("String ignoring certificate = " + string);
- } catch (IOException e) {
- // The downloaded certificate doesn't validate our https connection.
- e.printStackTrace();
- displayToast(R.string.certificate_error);
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (KeyManagementException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return string;
- }
-
- /**
- * Downloads the certificate from the parameter url bypassing self signed certificate SSL errors.
- * @param certificate_url_string
- * @return the certificate, as a string
- */
- private String downloadCertificateWithoutTrusting(String certificate_url_string) {
-
- String cert_string = "";
- HostnameVerifier hostnameVerifier = new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- return true;
- }
- };
-
- TrustManager[] trustAllCerts = new TrustManager[]{
- new X509TrustManager() {
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) {
- }
- public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) {
- }
- }
- };
-
- try {
- URL certificate_url = new URL(certificate_url_string);
- HttpsURLConnection urlConnection =
- (HttpsURLConnection)certificate_url.openConnection();
- urlConnection.setHostnameVerifier(hostnameVerifier);
-
- SSLContext sc = SSLContext.getInstance("TLS");
- sc.init(null, trustAllCerts, new java.security.SecureRandom());
-
- urlConnection.setSSLSocketFactory(sc.getSocketFactory());
-
- cert_string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
-
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // This should never happen
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (KeyManagementException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return cert_string;
- }
-
- /**
- * Downloads a JSON object from the given url.
- *
- * It first downloads the JSON object as a String, and then parses it to JSON object.
- * @param json_url
- * @param danger_on if the user completely trusts the certificate of the url address.
- * @return
- * @throws JSONException
- */
- private JSONObject getJSONFromProvider(String json_url, boolean danger_on) throws JSONException {
- String json_file_content = getStringFromProvider(json_url, danger_on);
- return new JSONObject(json_file_content);
- }
-
- /**
- * Tries to guess the provider.json url given the main provider url.
- * @param provider_main_url
- * @return the guessed provider.json url
- */
- private String guessProviderDotJsonURL(String provider_main_url) {
- return provider_main_url + "/provider.json";
- }
-
- /**
- * Logs out from the api url retrieved from the task.
- * @param task containing api url from which the user will log out
- * @return true if there were no exceptions
- */
- private boolean logOut(Bundle task) {
- DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext());
- int session_id_index = 0;
- //String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/sessions/" + client.getCookieStore().getCookies().get(0).getValue();
- try {
- String delete_url = task.getString(ConfigHelper.API_URL_KEY) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue();
- HttpDelete delete = new HttpDelete(delete_url);
- HttpResponse getResponse = client.execute(delete);
- HttpEntity responseEntity = getResponse.getEntity();
- responseEntity.consumeContent();
- } catch (ClientProtocolException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- } catch (IndexOutOfBoundsException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
- *
- * @param task containing the type of the certificate to be downloaded
- * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
- */
- private boolean getNewCert(Bundle task) {
- String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE);
- try {
- JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY);
- URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY));
- String new_cert_string_url = provider_main_url.toString() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY;
-
- if(type_of_certificate.equalsIgnoreCase(ConfigHelper.AUTHED_CERTIFICATE)) {
- HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY));
-
- CookieManager cookieManager = new CookieManager();
- cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie);
- CookieHandler.setDefault(cookieManager);
- }
-
- boolean danger_on = ConfigHelper.getBoolFromSharedPref(ConfigHelper.DANGER_ON);
- String cert_string = getStringFromProvider(new_cert_string_url, danger_on);
- if(!cert_string.isEmpty()) {
- // API returns concatenated cert & key. Split them for OpenVPN options
- String certificate = null, key = null;
- String[] certAndKey = cert_string.split("(?<=-\n)");
- for (int i=0; i < certAndKey.length-1; i++){
- if ( certAndKey[i].contains("KEY") )
- key = certAndKey[i++] + certAndKey[i];
- else if ( certAndKey[i].contains("CERTIFICATE") )
- certificate = certAndKey[i++] + certAndKey[i];
- }
- ConfigHelper.saveSharedPref(ConfigHelper.CERT_KEY, certificate);
- ConfigHelper.saveSharedPref(ConfigHelper.KEY_KEY, key);
- return true;
- } else {
- return false;
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- } catch (URISyntaxException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- }
-}
diff --git a/src/se/leap/leapclient/ProviderAPIResultReceiver.java b/src/se/leap/leapclient/ProviderAPIResultReceiver.java
deleted file mode 100644
index d82484c8..00000000
--- a/src/se/leap/leapclient/ProviderAPIResultReceiver.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-
-/**
- * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
- * @author parmegv
- *
- */
-public class ProviderAPIResultReceiver extends ResultReceiver {
- private Receiver mReceiver;
-
- public ProviderAPIResultReceiver(Handler handler) {
- super(handler);
- // TODO Auto-generated constructor stub
- }
-
- public void setReceiver(Receiver receiver) {
- mReceiver = receiver;
- }
-
- /**
- * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService.
- * @author parmegv
- *
- */
- public interface Receiver {
- public void onReceiveResult(int resultCode, Bundle resultData);
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (mReceiver != null) {
- mReceiver.onReceiveResult(resultCode, resultData);
- }
- }
-
-}
diff --git a/src/se/leap/leapclient/ProviderDetailFragment.java b/src/se/leap/leapclient/ProviderDetailFragment.java
deleted file mode 100644
index 600be58f..00000000
--- a/src/se/leap/leapclient/ProviderDetailFragment.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package se.leap.leapclient;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-public class ProviderDetailFragment extends DialogFragment {
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- try {
-
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View provider_detail_view = inflater.inflate(R.layout.provider_detail_fragment, null);
-
- JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY);
-
- final TextView domain = (TextView)provider_detail_view.findViewById(R.id.provider_detail_domain);
- domain.setText(provider_json.getString(ConfigHelper.DOMAIN));
- final TextView name = (TextView)provider_detail_view.findViewById(R.id.provider_detail_name);
- name.setText(provider_json.getJSONObject(ConfigHelper.NAME).getString("en"));
- final TextView description = (TextView)provider_detail_view.findViewById(R.id.provider_detail_description);
- description.setText(provider_json.getJSONObject(ConfigHelper.DESCRIPTION).getString("en"));
-
- builder.setView(provider_detail_view);
- builder.setTitle(R.string.provider_details_fragment_title);
-
- if(anon_allowed(provider_json)) {
- builder.setPositiveButton(R.string.use_anonymously_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.use_anonymously();
- }
- });
- }
-
- if(registration_allowed(provider_json)) {
- builder.setNegativeButton(R.string.login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.login();
- }
- });
- }
-
- return builder.create();
- } catch (JSONException e) {
- return null;
- }
- }
-
- private boolean anon_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(ConfigHelper.SERVICE_KEY);
- return service_description.has(ConfigHelper.ALLOWED_ANON) && service_description.getBoolean(ConfigHelper.ALLOWED_ANON);
- } catch (JSONException e) {
- return false;
- }
- }
-
- private boolean registration_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(ConfigHelper.SERVICE_KEY);
- return service_description.has(ConfigHelper.ALLOW_REGISTRATION_KEY) && service_description.getBoolean(ConfigHelper.ALLOW_REGISTRATION_KEY);
- } catch (JSONException e) {
- return false;
- }
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- ConfigHelper.removeFromSharedPref(ConfigHelper.PROVIDER_KEY);
- ConfigHelper.removeFromSharedPref(ConfigHelper.DANGER_ON);
- ConfigHelper.removeFromSharedPref(ConfigHelper.ALLOWED_ANON);
- ConfigHelper.removeFromSharedPref(ConfigHelper.EIP_SERVICE_KEY);
- }
-
- public static DialogFragment newInstance() {
- ProviderDetailFragment provider_detail_fragment = new ProviderDetailFragment();
- return provider_detail_fragment;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- interface_with_configuration_wizard = (ProviderDetailFragmentInterface) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement LogInDialogListener");
- }
- }
-
- public interface ProviderDetailFragmentInterface {
- public void login();
- public void use_anonymously();
- }
-
- ProviderDetailFragmentInterface interface_with_configuration_wizard;
-}
diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java
deleted file mode 100644
index 714ed5f4..00000000
--- a/src/se/leap/leapclient/ProviderListContent.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.net.URL;
-import java.net.MalformedURLException;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Models the provider list shown in the ConfigurationWizard.
- *
- * @author parmegv
- *
- */
-public class ProviderListContent {
-
- public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
-
- public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
-
- /**
- * Adds a new provider item to the end of the items map, and to the items list.
- * @param item
- */
- public static void addItem(ProviderItem item) {
- ITEMS.add(item);
- ITEM_MAP.put(String.valueOf(ITEMS.size()), item);
- }
-
- /**
- * A provider item.
- */
- public static class ProviderItem {
- public boolean custom = false;
- public String id;
- public String name;
- public String domain;
- public String provider_json_url;
- public JSONObject provider_json;
- public String provider_json_filename;
- public String eip_service_json_url;
- public String cert_json_url;
- public boolean danger_on = false;
-
- /**
- * @param name of the provider
- * @param urls_file_input_stream file input stream linking with the assets url file
- * @param custom if it's a new provider entered by the user or not
- * @param danger_on if the user trusts completely the new provider
- */
- public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
-
- try {
- byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
- urls_file_input_stream.read(urls_file_bytes);
- String urls_file_content = new String(urls_file_bytes);
- JSONObject file_contents = new JSONObject(urls_file_content);
- id = name;
- this.name = name;
- provider_json_url = file_contents.getString(ConfigHelper.PROVIDER_JSON_URL);
- domain = new URL(provider_json_url).getHost();
- //provider_json_filename = file_contents.getString("assets_json_provider");
- eip_service_json_url = file_contents.getString("json_eip_service");
- cert_json_url = file_contents.getString(ConfigHelper.CERT_KEY);
- this.custom = custom;
- this.danger_on = danger_on;
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * @param name of the provider
- * @param provider_json_url used to download provider.json file of the provider
- * @param provider_json already downloaded
- * @param custom if it's a new provider entered by the user or not
- * @param danger_on if the user trusts completely the new provider
- */
- public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) {
-
- try {
- id = name;
- //this.name = name;
- this.provider_json_url = provider_json_url;
- this.provider_json = provider_json;
- this.name = provider_json.getJSONObject("name").getString("en");
- domain = new URL(provider_json_url).getHost();
- eip_service_json_url = provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.EIP_SERVICE_API_PATH;
- cert_json_url = provider_json.getString("ca_cert_uri");
- this.custom = custom;
- this.danger_on = danger_on;
- if(custom)
- provider_json_filename = name + "_provider.json".replaceFirst("__", "_");
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- @Override
- public String toString() {
- return name;
- }
-
- public String getId() {
- return id;
- }
- }
-}
diff --git a/src/se/leap/leapclient/ProviderListFragment.java b/src/se/leap/leapclient/ProviderListFragment.java
deleted file mode 100644
index 2fca20e2..00000000
--- a/src/se/leap/leapclient/ProviderListFragment.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package se.leap.leapclient;
-
-import se.leap.leapclient.ProviderListContent.ProviderItem;
-import android.app.Activity;
-import android.app.ListFragment;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.content.Context;
-import android.widget.TwoLineListItem;
-
-/**
- * A list fragment representing a list of Providers. This fragment
- * also supports tablet devices by allowing list items to be given an
- * 'activated' state upon selection. This helps indicate which item is
- * currently being viewed in a {@link DashboardFragment}.
- * <p>
- * Activities containing this fragment MUST implement the {@link Callbacks}
- * interface.
- */
-public class ProviderListFragment extends ListFragment {
-
- private ArrayAdapter<ProviderItem> content_adapter;
-
- /**
- * The serialization (saved instance state) Bundle key representing the
- * activated item position. Only used on tablets.
- */
- private static final String STATE_ACTIVATED_POSITION = "activated_position";
-
- /**
- * The fragment's current callback object, which is notified of list item
- * clicks.
- */
- private Callbacks mCallbacks = sDummyCallbacks;
-
- /**
- * The current activated item position. Only used on tablets.
- */
- private int mActivatedPosition = ListView.INVALID_POSITION;
-
- /**
- * A callback interface that all activities containing this fragment must
- * implement. This mechanism allows activities to be notified of item
- * selections.
- */
- public interface Callbacks {
- /**
- * Callback for when an item has been selected.
- */
- public void onItemSelected(String id);
- }
-
- /**
- * A dummy implementation of the {@link Callbacks} interface that does
- * nothing. Used only when this fragment is not attached to an activity.
- */
- private static Callbacks sDummyCallbacks = new Callbacks() {
- @Override
- public void onItemSelected(String id) {
- }
- };
-
- /**
- * Mandatory empty constructor for the fragment manager to instantiate the
- * fragment (e.g. upon screen orientation changes).
- */
- public ProviderListFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- content_adapter = new ArrayAdapter<ProviderListContent.ProviderItem>(
- getActivity(),
- android.R.layout.simple_list_item_activated_2,
- ProviderListContent.ITEMS) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent){
- TwoLineListItem row;
- if (convertView == null) {
- LayoutInflater inflater = (LayoutInflater)getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- row = (TwoLineListItem)inflater.inflate(android.R.layout.simple_list_item_2, null);
- } else {
- row = (TwoLineListItem)convertView;
- }
- ProviderListContent.ProviderItem data = ProviderListContent.ITEMS.get(position);
- row.getText1().setText(data.domain);
- row.getText2().setText(data.name);
-
- return row;
- }
- };
- setListAdapter(content_adapter);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- return inflater.inflate(R.layout.provider_list_fragment, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // Restore the previously serialized activated item position.
- if (savedInstanceState != null
- && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
- setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
- }
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
-
- // Activities containing this fragment must implement its callbacks.
- if (!(activity instanceof Callbacks)) {
- throw new IllegalStateException("Activity must implement fragment's callbacks.");
- }
-
- mCallbacks = (Callbacks) activity;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
-
- // Reset the active callbacks interface to the dummy implementation.
- mCallbacks = sDummyCallbacks;
- }
-
- @Override
- public void onListItemClick(ListView listView, View view, int position, long id) {
- super.onListItemClick(listView, view, position, id);
-
- // Notify the active callbacks interface (the activity, if the
- // fragment is attached to one) that an item has been selected.
- mCallbacks.onItemSelected(ProviderListContent.ITEMS.get(position).id);
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mActivatedPosition != ListView.INVALID_POSITION) {
- // Serialize and persist the activated item position.
- outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
- }
- }
-
- /**
- * Turns on activate-on-click mode. When this mode is on, list items will be
- * given the 'activated' state when touched.
- */
- public void setActivateOnItemClick(boolean activateOnItemClick) {
- // When setting CHOICE_MODE_SINGLE, ListView will automatically
- // give items the 'activated' state when touched.
- getListView().setChoiceMode(activateOnItemClick
- ? ListView.CHOICE_MODE_SINGLE
- : ListView.CHOICE_MODE_NONE);
- }
-
- private void setActivatedPosition(int position) {
- if (position == ListView.INVALID_POSITION) {
- getListView().setItemChecked(mActivatedPosition, false);
- } else {
- getListView().setItemChecked(position, true);
- }
-
- mActivatedPosition = position;
- }
-}