summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java40
-rw-r--r--main/src/main/java/de/blinkt/openvpn/activities/MainActivity.java10
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java1
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java52
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java314
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java5
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java600
-rw-r--r--main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java376
-rw-r--r--main/src/main/res/layout-v21/profile_list_fabs.xml4
-rw-r--r--main/src/main/res/layout-v21/save_fab.xml22
-rw-r--r--main/src/main/res/layout/config_converter.xml14
-rw-r--r--main/src/main/res/layout/save_fab.xml11
-rw-r--r--main/src/main/res/layout/vpn_profile_list.xml2
-rwxr-xr-xmain/src/main/res/values/strings.xml2
14 files changed, 730 insertions, 723 deletions
diff --git a/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java b/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
index 262c6e9b..cace20ff 100644
--- a/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
+++ b/main/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java
@@ -25,8 +25,10 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
+import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
import junit.framework.Assert;
@@ -54,7 +56,7 @@ import de.blinkt.openvpn.views.FileSelectLayout;
import static de.blinkt.openvpn.views.FileSelectLayout.FileSelectCallback;
-public class ConfigConverter extends Activity implements FileSelectCallback {
+public class ConfigConverter extends Activity implements FileSelectCallback, View.OnClickListener {
public static final String IMPORT_PROFILE = "de.blinkt.openvpn.IMPORT_PROFILE";
private static final int RESULT_INSTALLPKCS12 = 7;
@@ -74,28 +76,39 @@ public class ConfigConverter extends Activity implements FileSelectCallback {
private String mCrlFileName;
@Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.fab_save)
+ userActionSaveProfile();
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.cancel) {
setResult(Activity.RESULT_CANCELED);
finish();
} else if (item.getItemId() == R.id.ok) {
- if (mResult == null) {
- log("Importing the config had error, cannot save it");
- return true;
- }
+ return userActionSaveProfile();
+ }
- Intent in = installPKCS12();
+ return super.onOptionsItemSelected(item);
- if (in != null)
- startActivityForResult(in, RESULT_INSTALLPKCS12);
- else
- saveProfile();
+ }
+ private boolean userActionSaveProfile() {
+ if (mResult == null) {
+ log(R.string.import_config_error);
+ Toast.makeText(this, R.string.import_config_error, Toast.LENGTH_LONG).show();
return true;
}
- return super.onOptionsItemSelected(item);
+ Intent in = installPKCS12();
+
+ if (in != null)
+ startActivityForResult(in, RESULT_INSTALLPKCS12);
+ else
+ saveProfile();
+ return true;
}
@Override
@@ -511,6 +524,10 @@ public class ConfigConverter extends Activity implements FileSelectCallback {
setContentView(R.layout.config_converter);
super.onCreate(savedInstanceState);
+ ImageButton fab_button = (ImageButton) findViewById(R.id.fab_save);
+ if(fab_button!=null)
+ fab_button.setOnClickListener(this);
+
if (savedInstanceState != null && savedInstanceState.containsKey(VPNPROFILE)) {
mResult = (VpnProfile) savedInstanceState.getSerializable(VPNPROFILE);
mAliasName = savedInstanceState.getString("mAliasName");
@@ -662,5 +679,4 @@ public class ConfigConverter extends Activity implements FileSelectCallback {
log(getString(ressourceId, formatArgs));
}
-
}
diff --git a/main/src/main/java/de/blinkt/openvpn/activities/MainActivity.java b/main/src/main/java/de/blinkt/openvpn/activities/MainActivity.java
index 1554a557..4aa7e120 100644
--- a/main/src/main/java/de/blinkt/openvpn/activities/MainActivity.java
+++ b/main/src/main/java/de/blinkt/openvpn/activities/MainActivity.java
@@ -9,6 +9,7 @@ import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4n.view.ViewPager;
import android.view.Menu;
@@ -18,6 +19,7 @@ import de.blinkt.openvpn.R;
import de.blinkt.openvpn.fragments.AboutFragment;
import de.blinkt.openvpn.fragments.FaqFragment;
import de.blinkt.openvpn.fragments.GeneralSettings;
+import de.blinkt.openvpn.fragments.LogFragment;
import de.blinkt.openvpn.fragments.SendDumpFragment;
import de.blinkt.openvpn.fragments.VPNProfileList;
import de.blinkt.openvpn.views.ScreenSlidePagerAdapter;
@@ -57,7 +59,8 @@ public class MainActivity extends Activity {
mPagerAdapter.addTab(R.string.crashdump, SendDumpFragment.class);
}
- //mPagerAdapter.addTab(R.string.openvpn_log, LogFragment.class);
+ if (isDirectToTV())
+ mPagerAdapter.addTab(R.string.openvpn_log, LogFragment.class);
mPagerAdapter.addTab(R.string.about, AboutFragment.class);
mPager.setAdapter(mPagerAdapter);
@@ -66,6 +69,11 @@ public class MainActivity extends Activity {
tabs.setViewPager(mPager);
}
+ private boolean isDirectToTV() {
+ return(getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+ || getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+ }
+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void disableToolbarElevation() {
ActionBar toolbar = getActionBar();
diff --git a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
index 89a98241..2420194d 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
@@ -38,5 +38,4 @@ public class ICSOpenVPNApplication extends Application {
//ACRA.init(this);
}
}
-
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 113142b7..9716f020 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -16,7 +16,6 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
-import android.net.NetworkRequest;
import android.net.VpnService;
import android.os.Binder;
import android.os.Build;
@@ -62,7 +61,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private static final String RESUME_VPN = "de.blinkt.openvpn.RESUME_VPN";
private static final int OPENVPN_STATUS = 1;
private static boolean mNotificationAlwaysVisible = false;
- private final Vector<String> mDnslist = new Vector<String>();
+ private final Vector<String> mDnslist = new Vector<>();
private final NetworkSpace mRoutes = new NetworkSpace();
private final NetworkSpace mRoutesv6 = new NetworkSpace();
private final IBinder mBinder = new LocalBinder();
@@ -81,7 +80,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private String mLastTunCfg;
private String mRemoteGW;
private final Object mProcessLock = new Object();
- private LollipopDeviceStateListener mLollipopDeviceStateListener;
// From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
public static String humanReadableByteCount(long bytes, boolean mbit) {
@@ -235,13 +233,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
//ignore exception
- } catch (NoSuchMethodException nsm) {
- VpnStatus.logException(nsm);
- } catch (IllegalArgumentException e) {
- VpnStatus.logException(e);
- } catch (IllegalAccessException e) {
- VpnStatus.logException(e);
- } catch (InvocationTargetException e) {
+ } catch (NoSuchMethodException | IllegalArgumentException |
+ InvocationTargetException | IllegalAccessException e) {
VpnStatus.logException(e);
}
@@ -325,6 +318,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
/* The intent is null when the service has been restarted */
if (intent == null) {
mProfile = ProfileManager.getLastConnectedProfile(this, false);
+ VpnStatus.logInfo(R.string.service_restarted);
/* Got no profile, just stop */
if (mProfile == null) {
@@ -412,7 +406,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
} else {
- HashMap<String, String> env = new HashMap<String, String>();
+ HashMap<String, String> env = new HashMap<>();
processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory);
}
@@ -428,7 +422,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
ProfileManager.setConnectedVpnProfile(this, mProfile);
/* TODO: At the moment we have no way to handle asynchronous PW input
- * Fixing will also allow to handle challenge/responsee authentication */
+ * Fixing will also allow to handle challenge/response authentication */
if (mProfile.needUserPWInput(true) != 0)
return START_NOT_STICKY;
@@ -439,17 +433,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
try {
Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3");
return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
+ } catch (IllegalArgumentException | InstantiationException | InvocationTargetException |
+ NoSuchMethodException | ClassNotFoundException | IllegalAccessException e ) {
e.printStackTrace();
}
return null;
@@ -572,7 +557,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
- if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist != null && mDnslist.size() >= 1) {
+ if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist.size() >= 1) {
// Check if the first DNS Server is in the VPN range
try {
ipAddress dnsServer = new ipAddress(new CIDRIP(mDnslist.get(0), 32), true);
@@ -652,22 +637,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
builder.allowFamily(OsConstants.AF_INET6);
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- void removeLollipopCMListener() {
- ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE);
- cm.unregisterNetworkCallback(mLollipopDeviceStateListener);
- mLollipopDeviceStateListener = null;
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- void addLollipopCMListener() {
- ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE);
- NetworkRequest.Builder nrb = new NetworkRequest.Builder();
-
- mLollipopDeviceStateListener = new LollipopDeviceStateListener();
- cm.registerNetworkCallback(nrb.build(), mLollipopDeviceStateListener);
- }
-
private void addLocalNetworksToRoutes() {
// Add local network interfaces
@@ -879,8 +848,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// CONNECTED
// Does not work :(
String msg = getString(resid);
- String ticker = msg;
- showNotification(msg + " " + logmessage, ticker, lowpriority, 0, level);
+ showNotification(msg + " " + logmessage, msg, lowpriority, 0, level);
}
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
index e4687c3c..086cdb44 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java
@@ -5,11 +5,15 @@
package de.blinkt.openvpn.core;
-import java.io.FileNotFoundException;
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.preference.PreferenceManager;
+
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.StreamCorruptedException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -17,207 +21,173 @@ import java.util.Set;
import de.blinkt.openvpn.VpnProfile;
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.preference.PreferenceManager;
-
public class ProfileManager {
- private static final String PREFS_NAME = "VPNList";
+ private static final String PREFS_NAME = "VPNList";
+ private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile";
+ private static ProfileManager instance;
+ private static VpnProfile mLastConnectedVpn = null;
+ private HashMap<String, VpnProfile> profiles = new HashMap<>();
+ private static VpnProfile tmpprofile = null;
- private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile";
+ private static VpnProfile get(String key) {
+ if (tmpprofile != null && tmpprofile.getUUIDString().equals(key))
+ return tmpprofile;
+ if (instance == null)
+ return null;
+ return instance.profiles.get(key);
+
+ }
- private static ProfileManager instance;
+ private ProfileManager() {
+ }
+ private static void checkInstance(Context context) {
+ if (instance == null) {
+ instance = new ProfileManager();
+ instance.loadVPNList(context);
+ }
+ }
- private static VpnProfile mLastConnectedVpn=null;
- private HashMap<String,VpnProfile> profiles=new HashMap<String, VpnProfile>();
- private static VpnProfile tmpprofile=null;
+ synchronized public static ProfileManager getInstance(Context context) {
+ checkInstance(context);
+ return instance;
+ }
+ public static void setConntectedVpnProfileDisconnected(Context c) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ Editor prefsedit = prefs.edit();
+ prefsedit.putString(LAST_CONNECTED_PROFILE, null);
+ prefsedit.apply();
- private static VpnProfile get(String key) {
- if (tmpprofile!=null && tmpprofile.getUUIDString().equals(key))
- return tmpprofile;
-
- if(instance==null)
- return null;
- return instance.profiles.get(key);
-
- }
+ }
+ public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ Editor prefsedit = prefs.edit();
-
- private ProfileManager() { }
-
- private static void checkInstance(Context context) {
- if(instance == null) {
- instance = new ProfileManager();
- instance.loadVPNList(context);
- }
- }
+ prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString());
+ prefsedit.apply();
+ mLastConnectedVpn = connectedrofile;
- synchronized public static ProfileManager getInstance(Context context) {
- checkInstance(context);
- return instance;
- }
-
- public static void setConntectedVpnProfileDisconnected(Context c) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- Editor prefsedit = prefs.edit();
- prefsedit.putString(LAST_CONNECTED_PROFILE, null);
- prefsedit.apply();
-
- }
+ }
- public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- Editor prefsedit = prefs.edit();
-
- prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString());
- prefsedit.apply();
- mLastConnectedVpn=connectedrofile;
-
- }
-
- public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+ public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
- boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false);
+ boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false);
if (onBoot && !useStartOnBoot)
return null;
-
- String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null);
- if(lastConnectedProfile!=null)
- return get(c, lastConnectedProfile);
- else
- return null;
- }
-
-
-
-
- public Collection<VpnProfile> getProfiles() {
- return profiles.values();
- }
-
- public VpnProfile getProfileByName(String name) {
- for (VpnProfile vpnp : profiles.values()) {
- if(vpnp.getName().equals(name)) {
- return vpnp;
- }
- }
- return null;
- }
-
- public void saveProfileList(Context context) {
- SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE);
- Editor editor = sharedprefs.edit();
- editor.putStringSet("vpnlist", profiles.keySet());
-
- // For reasing I do not understand at all
- // Android saves my prefs file only one time
- // if I remove the debug code below :(
- int counter = sharedprefs.getInt("counter", 0);
- editor.putInt("counter", counter+1);
- editor.apply();
-
- }
-
- public void addProfile(VpnProfile profile) {
- profiles.put(profile.getUUID().toString(),profile);
-
- }
-
- public static void setTemporaryProfile(VpnProfile tmp) {
- ProfileManager.tmpprofile = tmp;
- }
-
-
- public void saveProfile(Context context, VpnProfile profile) {
- ObjectOutputStream vpnfile;
- try {
- vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE));
-
- vpnfile.writeObject(profile);
- vpnfile.flush();
- vpnfile.close();
- } catch (IOException e) {
- VpnStatus.logException("saving VPN profile", e);
- throw new RuntimeException(e);
- }
- }
-
-
- private void loadVPNList(Context context) {
- profiles = new HashMap<String, VpnProfile>();
- SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE);
- Set<String> vlist = listpref.getStringSet("vpnlist", null);
- Exception exp =null;
- if(vlist==null){
- vlist = new HashSet<String>();
- }
-
- for (String vpnentry : vlist) {
- try {
- ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp"));
- VpnProfile vp = ((VpnProfile) vpnfile.readObject());
-
- // Sanity check
- if(vp==null || vp.mName==null || vp.getUUID()==null)
- continue;
- vp.upgradeProfile();
- profiles.put(vp.getUUID().toString(), vp);
+ String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null);
+ if (lastConnectedProfile != null)
+ return get(c, lastConnectedProfile);
+ else
+ return null;
+ }
+
+
+ public Collection<VpnProfile> getProfiles() {
+ return profiles.values();
+ }
+
+ public VpnProfile getProfileByName(String name) {
+ for (VpnProfile vpnp : profiles.values()) {
+ if (vpnp.getName().equals(name)) {
+ return vpnp;
+ }
+ }
+ return null;
+ }
+
+ public void saveProfileList(Context context) {
+ SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
+ Editor editor = sharedprefs.edit();
+ editor.putStringSet("vpnlist", profiles.keySet());
+
+ // For reasing I do not understand at all
+ // Android saves my prefs file only one time
+ // if I remove the debug code below :(
+ int counter = sharedprefs.getInt("counter", 0);
+ editor.putInt("counter", counter + 1);
+ editor.apply();
+
+ }
+
+ public void addProfile(VpnProfile profile) {
+ profiles.put(profile.getUUID().toString(), profile);
- } catch (StreamCorruptedException e) {
- exp=e;
- } catch (FileNotFoundException e) {
- exp=e;
- } catch (IOException e) {
- exp=e;
- } catch (ClassNotFoundException e) {
- exp=e;
- }
- if(exp!=null) {
- VpnStatus.logException("Loading VPN List",exp);
- }
- }
- }
+ }
- public int getNumberOfProfiles() {
- return profiles.size();
- }
+ public static void setTemporaryProfile(VpnProfile tmp) {
+ ProfileManager.tmpprofile = tmp;
+ }
+ public void saveProfile(Context context, VpnProfile profile) {
+ ObjectOutputStream vpnfile;
+ try {
+ vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"), Activity.MODE_PRIVATE));
- public void removeProfile(Context context,VpnProfile profile) {
- String vpnentry = profile.getUUID().toString();
- profiles.remove(vpnentry);
- saveProfileList(context);
- context.deleteFile(vpnentry + ".vp");
- if(mLastConnectedVpn==profile)
- mLastConnectedVpn=null;
-
- }
+ vpnfile.writeObject(profile);
+ vpnfile.flush();
+ vpnfile.close();
+ } catch (IOException e) {
+ VpnStatus.logException("saving VPN profile", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ private void loadVPNList(Context context) {
+ profiles = new HashMap<>();
+ SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
+ Set<String> vlist = listpref.getStringSet("vpnlist", null);
+ if (vlist == null) {
+ vlist = new HashSet<>();
+ }
+
+ for (String vpnentry : vlist) {
+ try {
+ ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp"));
+ VpnProfile vp = ((VpnProfile) vpnfile.readObject());
+
+ // Sanity check
+ if (vp == null || vp.mName == null || vp.getUUID() == null)
+ continue;
+
+ vp.upgradeProfile();
+ profiles.put(vp.getUUID().toString(), vp);
+ } catch (IOException | ClassNotFoundException e) {
+ VpnStatus.logException("Loading VPN List", e);
+ }
+ }
+ }
- public static VpnProfile get(Context context, String profileUUID) {
- checkInstance(context);
- return get(profileUUID);
- }
+ public void removeProfile(Context context, VpnProfile profile) {
+ String vpnentry = profile.getUUID().toString();
+ profiles.remove(vpnentry);
+ saveProfileList(context);
+ context.deleteFile(vpnentry + ".vp");
+ if (mLastConnectedVpn == profile)
+ mLastConnectedVpn = null;
+ }
+ public static VpnProfile get(Context context, String profileUUID) {
+ checkInstance(context);
+ return get(profileUUID);
+ }
- public static VpnProfile getLastConnectedVpn() {
- return mLastConnectedVpn;
- }
+ public static VpnProfile getLastConnectedVpn() {
+ return mLastConnectedVpn;
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index ea114d7e..d485a687 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -8,7 +8,6 @@ package de.blinkt.openvpn.core;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.os.Build;
import java.io.File;
@@ -67,14 +66,14 @@ public class VPNLaunchHelper {
public static String[] buildOpenvpnArgv(Context c) {
- Vector<String> args = new Vector<String>();
+ Vector<String> args = new Vector<>();
// Add fixed paramenters
//args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
args.add(writeMiniVPN(c));
args.add("--config");
- args.add(c.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
+ args.add(getConfigFilePath(c));
return args.toArray(new String[args.size()]);
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
index 8ab65424..9d19a0e8 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
@@ -6,6 +6,7 @@
package de.blinkt.openvpn.core;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -16,12 +17,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import org.w3c.dom.Text;
-
-import de.blinkt.openvpn.R;
-
import java.io.ByteArrayInputStream;
-import java.io.FileNotFoundException;
+import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.MessageDigest;
@@ -36,28 +33,30 @@ import java.util.Locale;
import java.util.UnknownFormatConversionException;
import java.util.Vector;
+import de.blinkt.openvpn.R;
+
public class VpnStatus {
- public static LinkedList<LogItem> logbuffer;
+ public static LinkedList<LogItem> logbuffer;
- private static Vector<LogListener> logListener;
- private static Vector<StateListener> stateListener;
- private static Vector<ByteCountListener> byteCountListener;
+ private static Vector<LogListener> logListener;
+ private static Vector<StateListener> stateListener;
+ private static Vector<ByteCountListener> byteCountListener;
- private static String mLaststatemsg="";
+ private static String mLaststatemsg = "";
- private static String mLaststate = "NOPROCESS";
+ private static String mLaststate = "NOPROCESS";
- private static int mLastStateresid=R.string.state_noprocess;
+ private static int mLastStateresid = R.string.state_noprocess;
- private static long mlastByteCount[]={0,0,0,0};
+ private static long mlastByteCount[] = {0, 0, 0, 0};
- public static void logException(LogLevel ll, String context, Exception e) {
+ public static void logException(LogLevel ll, String context, Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
LogItem li;
- if (context !=null) {
+ if (context != null) {
li = new LogItem(ll, R.string.unhandled_exception_context, e.getMessage(), sw.toString(), context);
} else {
li = new LogItem(ll, R.string.unhandled_exception, e.getMessage(), sw.toString());
@@ -75,18 +74,16 @@ public class VpnStatus {
private static final int MAXLOGENTRIES = 1000;
- public static final String MANAGMENT_PREFIX = "M:";
-
public enum ConnectionStatus {
LEVEL_CONNECTED,
LEVEL_VPNPAUSED,
LEVEL_CONNECTING_SERVER_REPLIED,
LEVEL_CONNECTING_NO_SERVER_REPLY_YET,
LEVEL_NONETWORK,
- LEVEL_NOTCONNECTED,
- LEVEL_AUTH_FAILED,
- LEVEL_WAITING_FOR_USER_INPUT,
- UNKNOWN_LEVEL
+ LEVEL_NOTCONNECTED,
+ LEVEL_AUTH_FAILED,
+ LEVEL_WAITING_FOR_USER_INPUT,
+ UNKNOWN_LEVEL
}
public enum LogLevel {
@@ -97,6 +94,7 @@ public class VpnStatus {
DEBUG(4);
protected int mValue;
+
LogLevel(int value) {
mValue = value;
}
@@ -107,59 +105,64 @@ public class VpnStatus {
public static LogLevel getEnumByValue(int value) {
switch (value) {
- case 1: return INFO;
- case 2: return ERROR;
- case 3: return WARNING;
- case 4: return DEBUG;
- default: return null;
+ case 1:
+ return INFO;
+ case 2:
+ return ERROR;
+ case 3:
+ return WARNING;
+ case 4:
+ return DEBUG;
+ default:
+ return null;
}
}
}
// keytool -printcert -jarfile de.blinkt.openvpn_85.apk
- public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109};
- public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43};
- public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57};
+ public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109};
+ public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43};
+ public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57};
public static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104};
- private static ConnectionStatus mLastLevel=ConnectionStatus.LEVEL_NOTCONNECTED;
+ private static ConnectionStatus mLastLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
- static {
- logbuffer = new LinkedList<LogItem>();
- logListener = new Vector<VpnStatus.LogListener>();
- stateListener = new Vector<VpnStatus.StateListener>();
- byteCountListener = new Vector<VpnStatus.ByteCountListener>();
- logInformation();
- }
+ static {
+ logbuffer = new LinkedList<>();
+ logListener = new Vector<>();
+ stateListener = new Vector<>();
+ byteCountListener = new Vector<>();
+ logInformation();
+ }
- public static class LogItem implements Parcelable {
+ public static class LogItem implements Parcelable {
- private Object [] mArgs = null;
- private String mMessage = null;
- private int mRessourceId;
- // Default log priority
- LogLevel mLevel = LogLevel.INFO;
- private long logtime = System.currentTimeMillis();
+ private Object[] mArgs = null;
+ private String mMessage = null;
+ private int mRessourceId;
+ // Default log priority
+ LogLevel mLevel = LogLevel.INFO;
+ private long logtime = System.currentTimeMillis();
private int mVerbosityLevel = -1;
- private LogItem(int ressourceId, Object[] args) {
- mRessourceId = ressourceId;
- mArgs = args;
- }
+ private LogItem(int ressourceId, Object[] args) {
+ mRessourceId = ressourceId;
+ mArgs = args;
+ }
public LogItem(LogLevel level, int verblevel, String message) {
- mMessage=message;
+ mMessage = message;
mLevel = level;
mVerbosityLevel = verblevel;
}
@Override
- public int describeContents() {
- return 0;
- }
+ public int describeContents() {
+ return 0;
+ }
@Override
@@ -173,65 +176,65 @@ public class VpnStatus {
dest.writeLong(logtime);
}
- public LogItem(Parcel in) {
- mArgs = in.readArray(Object.class.getClassLoader());
- mMessage = in.readString();
- mRessourceId = in.readInt();
- mLevel = LogLevel.getEnumByValue(in.readInt());
+ public LogItem(Parcel in) {
+ mArgs = in.readArray(Object.class.getClassLoader());
+ mMessage = in.readString();
+ mRessourceId = in.readInt();
+ mLevel = LogLevel.getEnumByValue(in.readInt());
mVerbosityLevel = in.readInt();
- logtime = in.readLong();
- }
+ logtime = in.readLong();
+ }
- public static final Parcelable.Creator<LogItem> CREATOR
- = new Parcelable.Creator<LogItem>() {
- public LogItem createFromParcel(Parcel in) {
- return new LogItem(in);
- }
+ public static final Parcelable.Creator<LogItem> CREATOR
+ = new Parcelable.Creator<LogItem>() {
+ public LogItem createFromParcel(Parcel in) {
+ return new LogItem(in);
+ }
- public LogItem[] newArray(int size) {
- return new LogItem[size];
- }
- };
+ public LogItem[] newArray(int size) {
+ return new LogItem[size];
+ }
+ };
- public LogItem(LogLevel loglevel,int ressourceId, Object... args) {
+ public LogItem(LogLevel loglevel, int ressourceId, Object... args) {
mRessourceId = ressourceId;
- mArgs =args;
+ mArgs = args;
mLevel = loglevel;
}
- public LogItem(LogLevel loglevel, String msg) {
- mLevel = loglevel;
- mMessage = msg;
- }
+ public LogItem(LogLevel loglevel, String msg) {
+ mLevel = loglevel;
+ mMessage = msg;
+ }
- public LogItem(LogLevel loglevel, int ressourceId) {
- mRessourceId =ressourceId;
- mLevel = loglevel;
- }
+ public LogItem(LogLevel loglevel, int ressourceId) {
+ mRessourceId = ressourceId;
+ mLevel = loglevel;
+ }
- public String getString(Context c) {
+ public String getString(Context c) {
try {
- if(mMessage !=null) {
- return mMessage;
- } else {
- if(c!=null) {
- if(mRessourceId==R.string.mobile_info)
- return getMobileInfoString(c);
- if(mArgs == null)
- return c.getString(mRessourceId);
- else
- return c.getString(mRessourceId, mArgs);
- } else {
- String str = String.format(Locale.ENGLISH,"Log (no context) resid %d", mRessourceId);
- if(mArgs !=null)
- str += TextUtils.join("|", mArgs);
-
-
- return str;
- }
- }
+ if (mMessage != null) {
+ return mMessage;
+ } else {
+ if (c != null) {
+ if (mRessourceId == R.string.mobile_info)
+ return getMobileInfoString(c);
+ if (mArgs == null)
+ return c.getString(mRessourceId);
+ else
+ return c.getString(mRessourceId, mArgs);
+ } else {
+ String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId);
+ if (mArgs != null)
+ str += TextUtils.join("|", mArgs);
+
+
+ return str;
+ }
+ }
} catch (UnknownFormatConversionException e) {
if (c != null)
throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null));
@@ -239,68 +242,66 @@ public class VpnStatus {
throw e;
} catch (java.util.FormatFlagsConversionMismatchException e) {
if (c != null)
- throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null),e.getConversion());
+ throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion());
else
throw e;
}
- }
+ }
- public LogLevel getLogLevel()
- {
+ public LogLevel getLogLevel() {
return mLevel;
}
// The lint is wrong here
- @SuppressLint("StringFormatMatches")
- private String getMobileInfoString(Context c) {
- c.getPackageManager();
- String apksign="error getting package signature";
-
- String version="error getting version";
- try {
- Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] der = cert.getEncoded();
- md.update(der);
- byte[] digest = md.digest();
-
- if (Arrays.equals(digest, officalkey))
- apksign = c.getString(R.string.official_build);
- else if (Arrays.equals(digest, officaldebugkey))
- apksign = c.getString(R.string.debug_build);
- else if (Arrays.equals(digest, amazonkey))
- apksign = "amazon version";
- else if (Arrays.equals(digest, fdroidkey))
+ @SuppressLint("StringFormatMatches")
+ private String getMobileInfoString(Context c) {
+ c.getPackageManager();
+ String apksign = "error getting package signature";
+
+ String version = "error getting version";
+ try {
+ Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] der = cert.getEncoded();
+ md.update(der);
+ byte[] digest = md.digest();
+
+ if (Arrays.equals(digest, officalkey))
+ apksign = c.getString(R.string.official_build);
+ else if (Arrays.equals(digest, officaldebugkey))
+ apksign = c.getString(R.string.debug_build);
+ else if (Arrays.equals(digest, amazonkey))
+ apksign = "amazon version";
+ else if (Arrays.equals(digest, fdroidkey))
apksign = "F-Droid built and signed version";
else
- apksign = c.getString(R.string.built_by,cert.getSubjectX500Principal().getName());
+ apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName());
- PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
- version = packageinfo.versionName;
+ PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
+ version = packageinfo.versionName;
- } catch (NameNotFoundException e) {
- } catch (CertificateException e) {
- } catch (NoSuchAlgorithmException e) {
- }
+ } catch (NameNotFoundException | CertificateException |
+ NoSuchAlgorithmException ignored) {
+ }
- Object[] argsext = Arrays.copyOf(mArgs, mArgs.length+2);
- argsext[argsext.length-1]=apksign;
- argsext[argsext.length-2]=version;
+ Object[] argsext = Arrays.copyOf(mArgs, mArgs.length + 2);
+ argsext[argsext.length - 1] = apksign;
+ argsext[argsext.length - 2] = version;
- return c.getString(R.string.mobile_info_extended, argsext);
+ return c.getString(R.string.mobile_info_extended, argsext);
- }
+ }
- public long getLogtime() {
- return logtime;
- }
+ public long getLogtime() {
+ return logtime;
+ }
public int getVerbosityLevel() {
- if (mVerbosityLevel==-1) {
+ if (mVerbosityLevel == -1) {
// Hack:
// For message not from OpenVPN, report the status level as log level
return mLevel.getInt();
@@ -309,90 +310,94 @@ public class VpnStatus {
}
}
+ public void saveLogToDisk(Context c) {
+
+ new File(c.getCacheDir(), "log.xml");
- public interface LogListener {
- void newLog(LogItem logItem);
- }
-
- public interface StateListener {
- void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level);
- }
-
- public interface ByteCountListener {
- void updateByteCount(long in, long out, long diffIn, long diffOut);
- }
-
- public synchronized static void logMessage(LogLevel level,String prefix, String message)
- {
- newLogItem(new LogItem(level, prefix + message));
-
- }
-
- public synchronized static void clearLog() {
- logbuffer.clear();
- logInformation();
- }
-
- private static void logInformation() {
- logInfo(R.string.mobile_info,Build.MODEL, Build.BOARD,Build.BRAND,Build.VERSION.SDK_INT);
- }
-
- public synchronized static void addLogListener(LogListener ll){
- logListener.add(ll);
- }
-
- public synchronized static void removeLogListener(LogListener ll) {
- logListener.remove(ll);
- }
-
- public synchronized static void addByteCountListener(ByteCountListener bcl) {
- bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]);
- byteCountListener.add(bcl);
- }
-
- public synchronized static void removeByteCountListener(ByteCountListener bcl) {
- byteCountListener.remove(bcl);
- }
-
-
- public synchronized static void addStateListener(StateListener sl){
- if(!stateListener.contains(sl)){
- stateListener.add(sl);
- if(mLaststate!=null)
- sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel);
- }
- }
-
- private static int getLocalizedState(String state){
- if (state.equals("CONNECTING"))
- return R.string.state_connecting;
- else if (state.equals("WAIT"))
- return R.string.state_wait;
- else if (state.equals("AUTH"))
- return R.string.state_auth;
- else if (state.equals("GET_CONFIG"))
- return R.string.state_get_config;
- else if (state.equals("ASSIGN_IP"))
- return R.string.state_assign_ip;
- else if (state.equals("ADD_ROUTES"))
- return R.string.state_add_routes;
- else if (state.equals("CONNECTED"))
- return R.string.state_connected;
- else if (state.equals("DISCONNECTED"))
- return R.string.state_disconnected;
- else if (state.equals("RECONNECTING"))
- return R.string.state_reconnecting;
- else if (state.equals("EXITING"))
- return R.string.state_exiting;
- else if (state.equals("RESOLVE"))
- return R.string.state_resolve;
- else if (state.equals("TCP_CONNECT"))
- return R.string.state_tcp_connect;
- else
- return R.string.unknown_state;
-
- }
+ }
+
+ public interface LogListener {
+ void newLog(LogItem logItem);
+ }
+
+ public interface StateListener {
+ void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level);
+ }
+
+ public interface ByteCountListener {
+ void updateByteCount(long in, long out, long diffIn, long diffOut);
+ }
+
+ public synchronized static void logMessage(LogLevel level, String prefix, String message) {
+ newLogItem(new LogItem(level, prefix + message));
+
+ }
+
+ public synchronized static void clearLog() {
+ logbuffer.clear();
+ logInformation();
+ }
+
+ private static void logInformation() {
+ logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT);
+ }
+
+ public synchronized static void addLogListener(LogListener ll) {
+ logListener.add(ll);
+ }
+
+ public synchronized static void removeLogListener(LogListener ll) {
+ logListener.remove(ll);
+ }
+
+ public synchronized static void addByteCountListener(ByteCountListener bcl) {
+ bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]);
+ byteCountListener.add(bcl);
+ }
+
+ public synchronized static void removeByteCountListener(ByteCountListener bcl) {
+ byteCountListener.remove(bcl);
+ }
+
+
+ public synchronized static void addStateListener(StateListener sl) {
+ if (!stateListener.contains(sl)) {
+ stateListener.add(sl);
+ if (mLaststate != null)
+ sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel);
+ }
+ }
+
+ private static int getLocalizedState(String state) {
+ if (state.equals("CONNECTING"))
+ return R.string.state_connecting;
+ else if (state.equals("WAIT"))
+ return R.string.state_wait;
+ else if (state.equals("AUTH"))
+ return R.string.state_auth;
+ else if (state.equals("GET_CONFIG"))
+ return R.string.state_get_config;
+ else if (state.equals("ASSIGN_IP"))
+ return R.string.state_assign_ip;
+ else if (state.equals("ADD_ROUTES"))
+ return R.string.state_add_routes;
+ else if (state.equals("CONNECTED"))
+ return R.string.state_connected;
+ else if (state.equals("DISCONNECTED"))
+ return R.string.state_disconnected;
+ else if (state.equals("RECONNECTING"))
+ return R.string.state_reconnecting;
+ else if (state.equals("EXITING"))
+ return R.string.state_exiting;
+ else if (state.equals("RESOLVE"))
+ return R.string.state_resolve;
+ else if (state.equals("TCP_CONNECT"))
+ return R.string.state_tcp_connect;
+ else
+ return R.string.unknown_state;
+
+ }
public static void updateStatePause(OpenVPNManagement.pauseReason pauseReason) {
switch (pauseReason) {
@@ -409,88 +414,84 @@ public class VpnStatus {
}
- private static ConnectionStatus getLevel(String state){
- String[] noreplyet = {"CONNECTING","WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"};
- String[] reply = {"AUTH","GET_CONFIG","ASSIGN_IP","ADD_ROUTES"};
- String[] connected = {"CONNECTED"};
- String[] notconnected = {"DISCONNECTED", "EXITING"};
-
- for(String x:noreplyet)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
-
- for(String x:reply)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED;
+ private static ConnectionStatus getLevel(String state) {
+ String[] noreplyet = {"CONNECTING", "WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"};
+ String[] reply = {"AUTH", "GET_CONFIG", "ASSIGN_IP", "ADD_ROUTES"};
+ String[] connected = {"CONNECTED"};
+ String[] notconnected = {"DISCONNECTED", "EXITING"};
- for(String x:connected)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_CONNECTED;
+ for (String x : noreplyet)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;
- for(String x:notconnected)
- if(state.equals(x))
- return ConnectionStatus.LEVEL_NOTCONNECTED;
+ for (String x : reply)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED;
- return ConnectionStatus.UNKNOWN_LEVEL;
+ for (String x : connected)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_CONNECTED;
- }
+ for (String x : notconnected)
+ if (state.equals(x))
+ return ConnectionStatus.LEVEL_NOTCONNECTED;
+ return ConnectionStatus.UNKNOWN_LEVEL;
+ }
- public synchronized static void removeStateListener(StateListener sl) {
- stateListener.remove(sl);
- }
+ public synchronized static void removeStateListener(StateListener sl) {
+ stateListener.remove(sl);
+ }
- synchronized public static LogItem[] getlogbuffer() {
+ synchronized public static LogItem[] getlogbuffer() {
- // The stoned way of java to return an array from a vector
- // brought to you by eclipse auto complete
- return logbuffer.toArray(new LogItem[logbuffer.size()]);
+ // The stoned way of java to return an array from a vector
+ // brought to you by eclipse auto complete
+ return logbuffer.toArray(new LogItem[logbuffer.size()]);
- }
+ }
- public static void updateStateString (String state, String msg) {
- int rid = getLocalizedState(state);
- ConnectionStatus level = getLevel(state);
- updateStateString(state, msg, rid, level);
- }
+ public static void updateStateString(String state, String msg) {
+ int rid = getLocalizedState(state);
+ ConnectionStatus level = getLevel(state);
+ updateStateString(state, msg, rid, level);
+ }
- public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) {
+ public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) {
// Workound for OpenVPN doing AUTH and wait and being connected
// Simply ignore these state
if (mLastLevel == ConnectionStatus.LEVEL_CONNECTED &&
- (state.equals("WAIT") || state.equals("AUTH")))
- {
- newLogItem(new LogItem((LogLevel.DEBUG), String.format("Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s",state,level.toString(),msg)));
+ (state.equals("WAIT") || state.equals("AUTH"))) {
+ newLogItem(new LogItem((LogLevel.DEBUG), String.format("Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s", state, level.toString(), msg)));
return;
}
- mLaststate= state;
- mLaststatemsg = msg;
- mLastStateresid = resid;
- mLastLevel = level;
-
+ mLaststate = state;
+ mLaststatemsg = msg;
+ mLastStateresid = resid;
+ mLastLevel = level;
for (StateListener sl : stateListener) {
- sl.updateState(state,msg,resid,level);
- }
+ sl.updateState(state, msg, resid, level);
+ }
//newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg)));
- }
+ }
- public static void logInfo(String message) {
- newLogItem(new LogItem(LogLevel.INFO, message));
- }
+ public static void logInfo(String message) {
+ newLogItem(new LogItem(LogLevel.INFO, message));
+ }
public static void logDebug(String message) {
newLogItem(new LogItem(LogLevel.DEBUG, message));
}
public static void logInfo(int resourceId, Object... args) {
- newLogItem(new LogItem(LogLevel.INFO, resourceId, args));
- }
+ newLogItem(new LogItem(LogLevel.INFO, resourceId, args));
+ }
public static void logDebug(int resourceId, Object... args) {
newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args));
@@ -498,19 +499,19 @@ public class VpnStatus {
private synchronized static void newLogItem(LogItem logItem) {
- logbuffer.addLast(logItem);
- if(logbuffer.size()>MAXLOGENTRIES)
- logbuffer.removeFirst();
+ logbuffer.addLast(logItem);
+ if (logbuffer.size() > MAXLOGENTRIES)
+ logbuffer.removeFirst();
- for (LogListener ll : logListener) {
- ll.newLog(logItem);
- }
- }
+ for (LogListener ll : logListener) {
+ ll.newLog(logItem);
+ }
+ }
- public static void logError(String msg) {
- newLogItem(new LogItem(LogLevel.ERROR, msg));
+ public static void logError(String msg) {
+ newLogItem(new LogItem(LogLevel.ERROR, msg));
- }
+ }
public static void logWarning(int resourceId, Object... args) {
newLogItem(new LogItem(LogLevel.WARNING, resourceId, args));
@@ -522,11 +523,12 @@ public class VpnStatus {
public static void logError(int resourceId) {
- newLogItem(new LogItem(LogLevel.ERROR, resourceId));
- }
- public static void logError(int resourceId, Object... args) {
- newLogItem(new LogItem(LogLevel.ERROR, resourceId, args));
- }
+ newLogItem(new LogItem(LogLevel.ERROR, resourceId));
+ }
+
+ public static void logError(int resourceId, Object... args) {
+ newLogItem(new LogItem(LogLevel.ERROR, resourceId, args));
+ }
public static void logMessageOpenVPN(LogLevel level, int ovpnlevel, String message) {
newLogItem(new LogItem(level, ovpnlevel, message));
@@ -535,19 +537,17 @@ public class VpnStatus {
public static synchronized void updateByteCount(long in, long out) {
- long lastIn = mlastByteCount[0];
- long lastOut = mlastByteCount[1];
- long diffIn = mlastByteCount[2] = in - lastIn;
- long diffOut = mlastByteCount[3] = out - lastOut;
-
-
-
- mlastByteCount = new long[] {in,out,diffIn,diffOut};
- for(ByteCountListener bcl:byteCountListener){
- bcl.updateByteCount(in, out, diffIn,diffOut);
- }
- }
+ long lastIn = mlastByteCount[0];
+ long lastOut = mlastByteCount[1];
+ long diffIn = mlastByteCount[2] = in - lastIn;
+ long diffOut = mlastByteCount[3] = out - lastOut;
+
+ mlastByteCount = new long[]{in, out, diffIn, diffOut};
+ for (ByteCountListener bcl : byteCountListener) {
+ bcl.updateByteCount(in, out, diffIn, diffOut);
+ }
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java b/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java
index e15fe509..cf712e7c 100644
--- a/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java
+++ b/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java
@@ -22,8 +22,10 @@ import android.view.*;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
+
import de.blinkt.openvpn.*;
import de.blinkt.openvpn.activities.ConfigConverter;
import de.blinkt.openvpn.activities.FileSelect;
@@ -34,120 +36,120 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.TreeSet;
-public class VPNProfileList extends ListFragment {
+public class VPNProfileList extends ListFragment implements OnClickListener {
- public final static int RESULT_VPN_DELETED = Activity.RESULT_FIRST_USER;
- public final static int RESULT_VPN_DUPLICATE = Activity.RESULT_FIRST_USER +1 ;
+ public final static int RESULT_VPN_DELETED = Activity.RESULT_FIRST_USER;
+ public final static int RESULT_VPN_DUPLICATE = Activity.RESULT_FIRST_USER + 1;
- private static final int MENU_ADD_PROFILE = Menu.FIRST;
+ private static final int MENU_ADD_PROFILE = Menu.FIRST;
- private static final int START_VPN_CONFIG = 92;
- private static final int SELECT_PROFILE = 43;
- private static final int IMPORT_PROFILE = 231;
+ private static final int START_VPN_CONFIG = 92;
+ private static final int SELECT_PROFILE = 43;
+ private static final int IMPORT_PROFILE = 231;
private static final int FILE_PICKER_RESULT_KITKAT = 392;
- private static final int MENU_IMPORT_PROFILE = Menu.FIRST +1;
+ private static final int MENU_IMPORT_PROFILE = Menu.FIRST + 1;
class VPNArrayAdapter extends ArrayAdapter<VpnProfile> {
- public VPNArrayAdapter(Context context, int resource,
- int textViewResourceId) {
- super(context, resource, textViewResourceId);
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- View v = super.getView(position, convertView, parent);
-
- View titleview = v.findViewById(R.id.vpn_list_item_left);
- titleview.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- VpnProfile profile =(VpnProfile) getListAdapter().getItem(position);
- startVPN(profile);
- }
- });
-
- View settingsview = v.findViewById(R.id.quickedit_settings);
- settingsview.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- VpnProfile editProfile = (VpnProfile) getListAdapter().getItem(position);
- editVPN(editProfile);
-
- }
- });
-
- return v;
- }
- }
-
-
-
+ public VPNArrayAdapter(Context context, int resource,
+ int textViewResourceId) {
+ super(context, resource, textViewResourceId);
+ }
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ View v = super.getView(position, convertView, parent);
+
+ View titleview = v.findViewById(R.id.vpn_list_item_left);
+ titleview.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ VpnProfile profile = (VpnProfile) getListAdapter().getItem(position);
+ startVPN(profile);
+ }
+ });
+
+ View settingsview = v.findViewById(R.id.quickedit_settings);
+ settingsview.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ VpnProfile editProfile = (VpnProfile) getListAdapter().getItem(position);
+ editVPN(editProfile);
+
+ }
+ });
+
+ return v;
+ }
+ }
+ private ArrayAdapter<VpnProfile> mArrayadapter;
+ protected VpnProfile mEditProfile = null;
- private ArrayAdapter<VpnProfile> mArrayadapter;
- protected VpnProfile mEditProfile=null;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
+ class MiniImageGetter implements ImageGetter {
- }
+ @Override
+ public Drawable getDrawable(String source) {
+ Drawable d = null;
+ if ("ic_menu_add".equals(source))
+ d = getActivity().getResources().getDrawable(R.drawable.ic_menu_add_grey);
+ else if ("ic_menu_archive".equals(source))
+ d = getActivity().getResources().getDrawable(R.drawable.ic_menu_import_grey);
+
+
+ if (d != null) {
+ d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ return d;
+ } else {
+ return null;
+ }
+ }
+ }
- class MiniImageGetter implements ImageGetter {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.vpn_profile_list, container, false);
- @Override
- public Drawable getDrawable(String source) {
- Drawable d=null;
- if ("ic_menu_add".equals(source))
- d = getActivity().getResources().getDrawable(R.drawable.ic_menu_add_grey);
- else if("ic_menu_archive".equals(source))
- d = getActivity().getResources().getDrawable(R.drawable.ic_menu_import_grey);
-
-
-
- if(d!=null) {
- d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
- return d;
- }else{
- return null;
- }
- }
- }
+ TextView newvpntext = (TextView) v.findViewById(R.id.add_new_vpn_hint);
+ TextView importvpntext = (TextView) v.findViewById(R.id.import_vpn_hint);
+ newvpntext.setText(Html.fromHtml(getString(R.string.add_new_vpn_hint), new MiniImageGetter(), null));
+ importvpntext.setText(Html.fromHtml(getString(R.string.vpn_import_hint), new MiniImageGetter(), null));
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.vpn_profile_list, container,false);
+ ImageButton fab_add = (ImageButton) v.findViewById(R.id.fab_add);
+ ImageButton fab_import = (ImageButton) v.findViewById(R.id.fab_import);
+ if (fab_add != null)
+ fab_add.setOnClickListener(this);
- TextView newvpntext = (TextView) v.findViewById(R.id.add_new_vpn_hint);
- TextView importvpntext = (TextView) v.findViewById(R.id.import_vpn_hint);
-
- newvpntext.setText(Html.fromHtml(getString(R.string.add_new_vpn_hint),new MiniImageGetter(),null));
- importvpntext.setText(Html.fromHtml(getString(R.string.vpn_import_hint),new MiniImageGetter(),null));
+ if (fab_import != null)
+ fab_import.setOnClickListener(this);
- return v;
+ return v;
- }
+ }
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- setListAdapter();
- }
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setListAdapter();
+ }
static class VpnProfileNameComparator implements Comparator<VpnProfile> {
@@ -172,52 +174,63 @@ public class VPNProfileList extends ListFragment {
}
- private void setListAdapter() {
- mArrayadapter = new VPNArrayAdapter(getActivity(),R.layout.vpn_list_item,R.id.vpn_item_title);
- Collection<VpnProfile> allvpn = getPM().getProfiles();
+ private void setListAdapter() {
+ mArrayadapter = new VPNArrayAdapter(getActivity(), R.layout.vpn_list_item, R.id.vpn_item_title);
+ Collection<VpnProfile> allvpn = getPM().getProfiles();
TreeSet<VpnProfile> sortedset = new TreeSet<VpnProfile>(new VpnProfileNameComparator());
sortedset.addAll(allvpn);
mArrayadapter.addAll(sortedset);
setListAdapter(mArrayadapter);
- }
-
+ }
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- menu.add(0, MENU_ADD_PROFILE, 0 , R.string.menu_add_profile)
- .setIcon(R.drawable.ic_menu_add)
- .setAlphabeticShortcut('a')
- .setTitleCondensed(getActivity().getString(R.string.add))
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ menu.add(0, MENU_ADD_PROFILE, 0, R.string.menu_add_profile)
+ .setIcon(R.drawable.ic_menu_add)
+ .setAlphabeticShortcut('a')
+ .setTitleCondensed(getActivity().getString(R.string.add))
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- menu.add(0, MENU_IMPORT_PROFILE, 0, R.string.menu_import)
- .setIcon(R.drawable.ic_menu_import)
- .setAlphabeticShortcut('i')
- .setTitleCondensed(getActivity().getString(R.string.menu_import_short))
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT );
- }
+ menu.add(0, MENU_IMPORT_PROFILE, 0, R.string.menu_import)
+ .setIcon(R.drawable.ic_menu_import)
+ .setAlphabeticShortcut('i')
+ .setTitleCondensed(getActivity().getString(R.string.menu_import_short))
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- final int itemId = item.getItemId();
- if (itemId == MENU_ADD_PROFILE) {
- onAddOrDuplicateProfile(null);
- return true;
- } else if (itemId == MENU_IMPORT_PROFILE) {
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == MENU_ADD_PROFILE) {
+ onAddOrDuplicateProfile(null);
+ return true;
+ } else if (itemId == MENU_IMPORT_PROFILE) {
return startImportConfigFilePicker();
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.fab_import:
+ startImportConfigFilePicker();
+ break;
+ case R.id.fab_add:
+ onAddOrDuplicateProfile(null);
+ break;
+ }
+ }
private boolean startImportConfigFilePicker() {
- boolean startOldFileDialog=true;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
- startOldFileDialog = ! startFilePicker();
+ boolean startOldFileDialog = true;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
+ startOldFileDialog = !startFilePicker();
if (startOldFileDialog)
startImportConfig();
@@ -228,8 +241,8 @@ public class VPNProfileList extends ListFragment {
@TargetApi(Build.VERSION_CODES.KITKAT)
private boolean startFilePicker() {
- Intent i = Utils.getFilePickerIntent(getActivity(), Utils.FileType.OVPN_CONFIG);
- if (i!=null) {
+ Intent i = Utils.getFilePickerIntent(getActivity(), Utils.FileType.OVPN_CONFIG);
+ if (i != null) {
startActivityForResult(i, FILE_PICKER_RESULT_KITKAT);
return true;
} else
@@ -237,32 +250,29 @@ public class VPNProfileList extends ListFragment {
}
private void startImportConfig() {
- Intent intent = new Intent(getActivity(),FileSelect.class);
- intent.putExtra(FileSelect.NO_INLINE_SELECTION, true);
- intent.putExtra(FileSelect.WINDOW_TITLE, R.string.import_configuration_file);
- startActivityForResult(intent, SELECT_PROFILE);
- }
-
-
-
+ Intent intent = new Intent(getActivity(), FileSelect.class);
+ intent.putExtra(FileSelect.NO_INLINE_SELECTION, true);
+ intent.putExtra(FileSelect.WINDOW_TITLE, R.string.import_configuration_file);
+ startActivityForResult(intent, SELECT_PROFILE);
+ }
- private void onAddOrDuplicateProfile(final VpnProfile mCopyProfile) {
- Context context = getActivity();
- if (context != null) {
- final EditText entry = new EditText(context);
- entry.setSingleLine();
+ private void onAddOrDuplicateProfile(final VpnProfile mCopyProfile) {
+ Context context = getActivity();
+ if (context != null) {
+ final EditText entry = new EditText(context);
+ entry.setSingleLine();
- AlertDialog.Builder dialog = new AlertDialog.Builder(context);
+ AlertDialog.Builder dialog = new AlertDialog.Builder(context);
if (mCopyProfile == null)
- dialog.setTitle(R.string.menu_add_profile);
+ dialog.setTitle(R.string.menu_add_profile);
else {
dialog.setTitle(context.getString(R.string.duplicate_profile_title, mCopyProfile.mName));
entry.setText(getString(R.string.copy_of_profile, mCopyProfile.mName));
}
dialog.setMessage(R.string.add_profile_name_prompt);
- dialog.setView(entry);
+ dialog.setView(entry);
dialog.setNeutralButton(R.string.menu_import_short,
new DialogInterface.OnClickListener() {
@@ -271,7 +281,7 @@ public class VPNProfileList extends ListFragment {
startImportConfigFilePicker();
}
});
- dialog.setPositiveButton(android.R.string.ok,
+ dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -292,32 +302,32 @@ public class VPNProfileList extends ListFragment {
});
- dialog.setNegativeButton(android.R.string.cancel, null);
- dialog.create().show();
- }
+ dialog.setNegativeButton(android.R.string.cancel, null);
+ dialog.create().show();
+ }
- }
+ }
- private void addProfile(VpnProfile profile) {
- getPM().addProfile(profile);
- getPM().saveProfileList(getActivity());
- getPM().saveProfile(getActivity(),profile);
- mArrayadapter.add(profile);
- }
+ private void addProfile(VpnProfile profile) {
+ getPM().addProfile(profile);
+ getPM().saveProfileList(getActivity());
+ getPM().saveProfile(getActivity(), profile);
+ mArrayadapter.add(profile);
+ }
- private ProfileManager getPM() {
- return ProfileManager.getInstance(getActivity());
- }
+ private ProfileManager getPM() {
+ return ProfileManager.getInstance(getActivity());
+ }
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
- if(resultCode == RESULT_VPN_DELETED){
- if(mArrayadapter != null && mEditProfile !=null)
- mArrayadapter.remove(mEditProfile);
- } else if (resultCode == RESULT_VPN_DUPLICATE && data != null) {
+ if (resultCode == RESULT_VPN_DELETED) {
+ if (mArrayadapter != null && mEditProfile != null)
+ mArrayadapter.remove(mEditProfile);
+ } else if (resultCode == RESULT_VPN_DUPLICATE && data != null) {
String profileUUID = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
VpnProfile profile = ProfileManager.get(getActivity(), profileUUID);
if (profile != null)
@@ -325,37 +335,37 @@ public class VPNProfileList extends ListFragment {
}
- if(resultCode != Activity.RESULT_OK)
- return;
+ if (resultCode != Activity.RESULT_OK)
+ return;
- if (requestCode == START_VPN_CONFIG) {
- String configuredVPN = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
+ if (requestCode == START_VPN_CONFIG) {
+ String configuredVPN = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
- VpnProfile profile = ProfileManager.get(getActivity(),configuredVPN);
- getPM().saveProfile(getActivity(), profile);
- // Name could be modified, reset List adapter
- setListAdapter();
+ VpnProfile profile = ProfileManager.get(getActivity(), configuredVPN);
+ getPM().saveProfile(getActivity(), profile);
+ // Name could be modified, reset List adapter
+ setListAdapter();
- } else if(requestCode== SELECT_PROFILE) {
+ } else if (requestCode == SELECT_PROFILE) {
String fileData = data.getStringExtra(FileSelect.RESULT_DATA);
Uri uri = new Uri.Builder().path(fileData).scheme("file").build();
startConfigImport(uri);
- } else if(requestCode == IMPORT_PROFILE) {
- String profileUUID = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
- mArrayadapter.add(ProfileManager.get(getActivity(), profileUUID));
- } else if(requestCode == FILE_PICKER_RESULT_KITKAT) {
+ } else if (requestCode == IMPORT_PROFILE) {
+ String profileUUID = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
+ mArrayadapter.add(ProfileManager.get(getActivity(), profileUUID));
+ } else if (requestCode == FILE_PICKER_RESULT_KITKAT) {
if (data != null) {
Uri uri = data.getData();
startConfigImport(uri);
}
}
- }
+ }
private void startConfigImport(Uri uri) {
- Intent startImport = new Intent(getActivity(),ConfigConverter.class);
+ Intent startImport = new Intent(getActivity(), ConfigConverter.class);
startImport.setAction(ConfigConverter.IMPORT_PROFILE);
startImport.setData(uri);
startActivityForResult(startImport, IMPORT_PROFILE);
@@ -363,20 +373,20 @@ public class VPNProfileList extends ListFragment {
private void editVPN(VpnProfile profile) {
- mEditProfile =profile;
- Intent vprefintent = new Intent(getActivity(),VPNPreferences.class)
- .putExtra(getActivity().getPackageName() + ".profileUUID", profile.getUUID().toString());
+ mEditProfile = profile;
+ Intent vprefintent = new Intent(getActivity(), VPNPreferences.class)
+ .putExtra(getActivity().getPackageName() + ".profileUUID", profile.getUUID().toString());
- startActivityForResult(vprefintent,START_VPN_CONFIG);
- }
+ startActivityForResult(vprefintent, START_VPN_CONFIG);
+ }
- private void startVPN(VpnProfile profile) {
+ private void startVPN(VpnProfile profile) {
- getPM().saveProfile(getActivity(), profile);
+ getPM().saveProfile(getActivity(), profile);
- Intent intent = new Intent(getActivity(),LaunchVPN.class);
- intent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
- intent.setAction(Intent.ACTION_MAIN);
- startActivity(intent);
- }
+ Intent intent = new Intent(getActivity(), LaunchVPN.class);
+ intent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
+ intent.setAction(Intent.ACTION_MAIN);
+ startActivity(intent);
+ }
}
diff --git a/main/src/main/res/layout-v21/profile_list_fabs.xml b/main/src/main/res/layout-v21/profile_list_fabs.xml
index 5ea6512d..28d393f0 100644
--- a/main/src/main/res/layout-v21/profile_list_fabs.xml
+++ b/main/src/main/res/layout-v21/profile_list_fabs.xml
@@ -9,7 +9,7 @@
tools:ignore="InconsistentLayout">
<ImageButton
- android:id="@+id/add_button"
+ android:id="@+id/fab_import"
android:layout_width="@dimen/round_button_diameter"
android:layout_height="@dimen/round_button_diameter"
android:layout_gravity="end|bottom"
@@ -23,7 +23,7 @@
<ImageButton
android:contentDescription="@string/add_profile"
- android:id="@+id/import_button"
+ android:id="@+id/fab_add"
android:layout_width="@dimen/round_button_diameter"
android:layout_height="@dimen/round_button_diameter"
android:layout_gravity="end|bottom"
diff --git a/main/src/main/res/layout-v21/save_fab.xml b/main/src/main/res/layout-v21/save_fab.xml
new file mode 100644
index 00000000..55fdecc6
--- /dev/null
+++ b/main/src/main/res/layout-v21/save_fab.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ ~ Copyright (c) 2012-2015 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+ tools:ignore="InconsistentLayout"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/fab_save"
+ android:layout_width="@dimen/round_button_diameter"
+ android:layout_height="@dimen/round_button_diameter"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="16dp"
+ android:background="@drawable/oval_ripple"
+ android:elevation="1dp"
+ android:src="@android:drawable/ic_menu_save"
+ android:stateListAnimator="@anim/fab_anim"
+ android:tint="@android:color/white"
+ tools:showIn="@layout/config_converter" /> \ No newline at end of file
diff --git a/main/src/main/res/layout/config_converter.xml b/main/src/main/res/layout/config_converter.xml
index 96381b60..fe4ca31f 100644
--- a/main/src/main/res/layout/config_converter.xml
+++ b/main/src/main/res/layout/config_converter.xml
@@ -3,10 +3,12 @@
~ Copyright (c) 2012-2014 Arne Schwabe
~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
+<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/stdpadding"
android:orientation="vertical">
@@ -43,6 +45,6 @@
android:id="@+id/textView"/>
</LinearLayout>
-
-
-</ScrollView> \ No newline at end of file
+ </ScrollView>
+ <include layout="@layout/save_fab" />
+</FrameLayout>
diff --git a/main/src/main/res/layout/save_fab.xml b/main/src/main/res/layout/save_fab.xml
new file mode 100644
index 00000000..e3cae9ab
--- /dev/null
+++ b/main/src/main/res/layout/save_fab.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (c) 2012-2014 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+</merge> \ No newline at end of file
diff --git a/main/src/main/res/layout/vpn_profile_list.xml b/main/src/main/res/layout/vpn_profile_list.xml
index 082ffd77..3f295f2d 100644
--- a/main/src/main/res/layout/vpn_profile_list.xml
+++ b/main/src/main/res/layout/vpn_profile_list.xml
@@ -74,6 +74,6 @@
</LinearLayout>
- <!-- <include layout="@layout/profile_list_fabs" /> -->
+ <include layout="@layout/profile_list_fabs" />
</FrameLayout>
diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml
index 88e61928..6f64d2ba 100755
--- a/main/src/main/res/values/strings.xml
+++ b/main/src/main/res/values/strings.xml
@@ -380,5 +380,7 @@
<string name="tls_cipher_alert">Newer OpenVPN for Android versions (0.6.29/March 2015) use a more secure default for the allowed cipher suites (tls-cipher \"DEFAULT:!EXP:!PSK:!SRP:!kRSA\"). Unfortunately, omitting the less secure cipher suites and export cipher suites, especially the omission of cipher suites that do not support Perfect Forward Secrecy (Diffie-Hellman) causes some problems. This usually caused by an well-intentioned but poorly executed attempts to strengthen TLS security by setting tls-cipher on the server or some embedded OSes with stripped down SSL (e.g. MikroTik).\nTo solve this problem the problem, set the tls-cipher settings on the server to reasonable default like tls-cipher \"DEFAULT:!EXP:!PSK:!SRP:!kRSA\". To work around the problem on the client add the custom option tls-cipher DEFAULT on the Android client.</string>
<string name="message_no_user_edit">This profile has been added from an external app (%s) and has been marked as not user editable.</string>
<string name="crl_file">Certificate Revocation List</string>
+ <string name="service_restarted">Restarting OpenVPN Service (App crashed probably crashed or killed for memory pressure)</string>
+ <string name="import_config_error">Importing the config yielded an error, cannot save it</string>
</resources>