From 4c991f2fc906bb66f060c15bc27a4fad0fb4805a Mon Sep 17 00:00:00 2001
From: Arne Schwabe <arne@rfc2549.org>
Date: Thu, 3 May 2012 22:18:56 +0200
Subject: add delete Profile support add Config Parser begin openvpn config =>
 Vpn Profile Converter

---
 src/de/blinkt/openvpn/LaunchVPN.java               | 252 +++++++++++----------
 src/de/blinkt/openvpn/OpenVPN.java                 |   3 +-
 src/de/blinkt/openvpn/OpenVpnManagementThread.java |  21 +-
 src/de/blinkt/openvpn/OpenVpnService.java          |  19 +-
 src/de/blinkt/openvpn/Settings_Obscure.java        |   6 +-
 src/de/blinkt/openvpn/VPNProfileList.java          | 191 +++++++++++-----
 src/de/blinkt/openvpn/VpnProfile.java              |   9 +-
 7 files changed, 308 insertions(+), 193 deletions(-)

diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java
index caeedc09..7a034e4c 100644
--- a/src/de/blinkt/openvpn/LaunchVPN.java
+++ b/src/de/blinkt/openvpn/LaunchVPN.java
@@ -22,6 +22,7 @@ import java.util.Vector;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.ListActivity;
+import android.content.ActivityNotFoundException;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.VpnService;
@@ -70,27 +71,27 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 	private ProfileManager mPM;
 	private VpnProfile mSelectedProfile;
 
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
+	@Override
+	public void onCreate(Bundle icicle) {
+		super.onCreate(icicle);
+
+		// Resolve the intent
+
+		final Intent intent = getIntent();
+		final String action = intent.getAction();
 
-        // Resolve the intent
+		mPM =ProfileManager.getInstance();
+		if(mPM.getNumberOfProfiles() == 0) {
+			mPM.loadVPNList(this);
+		}
 
-        final Intent intent = getIntent();
-        final String action = intent.getAction();
-        
-        mPM =ProfileManager.getInstance();
-        if(mPM.getNumberOfProfiles() == 0) {
-        	mPM.loadVPNList(this);
-        }
-        
 
-        // If the intent is a request to create a shortcut, we'll do that and exit
+		// If the intent is a request to create a shortcut, we'll do that and exit
 
 		if(Intent.ACTION_MAIN.equals(action)) {
 			// we got called to be the starting point, most likely a shortcut
 			String shortcutUUID = intent.getStringExtra( EXTRA_KEY);
-			
+
 			VpnProfile profileToConnect = ProfileManager.get(shortcutUUID);
 			if(profileToConnect ==null) {
 				Toast notfound = Toast.makeText(this, R.string.shortcut_profile_notfound, Toast.LENGTH_SHORT);
@@ -98,111 +99,111 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 				finish();
 				return;
 			}
-			
+
 			mSelectedProfile = profileToConnect;
 			launchVPN();
-			
-			
-			
+
+
+
 		} else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
 			createListView();
 		}
-		
-          
-        
-        
-		  
-		  
-
-    }
-
-    private void createListView() {
-        ListView lv = getListView();
-		  //lv.setTextFilterEnabled(true);
-        
-        Collection<VpnProfile> vpnlist = mPM.getProfiles();
-        
-        Vector<String> vpnnames=new Vector<String>();
-        for (VpnProfile vpnProfile : vpnlist) {
-        	vpnnames.add(vpnProfile.mName);
+
+
+
+
+
+
+
+	}
+
+	private void createListView() {
+		ListView lv = getListView();
+		//lv.setTextFilterEnabled(true);
+
+		Collection<VpnProfile> vpnlist = mPM.getProfiles();
+
+		Vector<String> vpnnames=new Vector<String>();
+		for (VpnProfile vpnProfile : vpnlist) {
+			vpnnames.add(vpnProfile.mName);
 		}
-        
-        
-        
-		  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,vpnnames);
-		  lv.setAdapter(adapter);
-        
-		  lv.setOnItemClickListener(this);
+
+
+
+		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,vpnnames);
+		lv.setAdapter(adapter);
+
+		lv.setOnItemClickListener(this);
 	}
 
 	/**
-     * This function creates a shortcut and returns it to the caller.  There are actually two 
-     * intents that you will send back.
-     * 
-     * The first intent serves as a container for the shortcut and is returned to the launcher by 
-     * setResult().  This intent must contain three fields:
-     * 
-     * <ul>
-     * <li>{@link android.content.Intent#EXTRA_SHORTCUT_INTENT} The shortcut intent.</li>
-     * <li>{@link android.content.Intent#EXTRA_SHORTCUT_NAME} The text that will be displayed with
-     * the shortcut.</li>
-     * <li>{@link android.content.Intent#EXTRA_SHORTCUT_ICON} The shortcut's icon, if provided as a
-     * bitmap, <i>or</i> {@link android.content.Intent#EXTRA_SHORTCUT_ICON_RESOURCE} if provided as
-     * a drawable resource.</li>
-     * </ul>
-     * 
-     * If you use a simple drawable resource, note that you must wrapper it using
-     * {@link android.content.Intent.ShortcutIconResource}, as shown below.  This is required so
-     * that the launcher can access resources that are stored in your application's .apk file.  If 
-     * you return a bitmap, such as a thumbnail, you can simply put the bitmap into the extras 
-     * bundle using {@link android.content.Intent#EXTRA_SHORTCUT_ICON}.
-     * 
-     * The shortcut intent can be any intent that you wish the launcher to send, when the user 
-     * clicks on the shortcut.  Typically this will be {@link android.content.Intent#ACTION_VIEW} 
-     * with an appropriate Uri for your content, but any Intent will work here as long as it 
-     * triggers the desired action within your Activity.
-     * @param profile 
-     */
-    private void setupShortcut(VpnProfile profile) {
-        // First, set up the shortcut intent.  For this example, we simply create an intent that
-        // will bring us directly back to this activity.  A more typical implementation would use a 
-        // data Uri in order to display a more specific result, or a custom action in order to 
-        // launch a specific operation.
-
-        Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
-        shortcutIntent.setClass(this, LaunchVPN.class);
-        shortcutIntent.putExtra(EXTRA_KEY,profile.getUUID().toString());
-
-        // Then, set up the container intent (the response to the caller)
-
-        Intent intent = new Intent();
-        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
-        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, profile.getName());
-        Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
-                this,  R.drawable.icon);
-        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
-
-        // Now, return the result to the launcher
-
-        setResult(RESULT_OK, intent);
-    }
-    
+	 * This function creates a shortcut and returns it to the caller.  There are actually two 
+	 * intents that you will send back.
+	 * 
+	 * The first intent serves as a container for the shortcut and is returned to the launcher by 
+	 * setResult().  This intent must contain three fields:
+	 * 
+	 * <ul>
+	 * <li>{@link android.content.Intent#EXTRA_SHORTCUT_INTENT} The shortcut intent.</li>
+	 * <li>{@link android.content.Intent#EXTRA_SHORTCUT_NAME} The text that will be displayed with
+	 * the shortcut.</li>
+	 * <li>{@link android.content.Intent#EXTRA_SHORTCUT_ICON} The shortcut's icon, if provided as a
+	 * bitmap, <i>or</i> {@link android.content.Intent#EXTRA_SHORTCUT_ICON_RESOURCE} if provided as
+	 * a drawable resource.</li>
+	 * </ul>
+	 * 
+	 * If you use a simple drawable resource, note that you must wrapper it using
+	 * {@link android.content.Intent.ShortcutIconResource}, as shown below.  This is required so
+	 * that the launcher can access resources that are stored in your application's .apk file.  If 
+	 * you return a bitmap, such as a thumbnail, you can simply put the bitmap into the extras 
+	 * bundle using {@link android.content.Intent#EXTRA_SHORTCUT_ICON}.
+	 * 
+	 * The shortcut intent can be any intent that you wish the launcher to send, when the user 
+	 * clicks on the shortcut.  Typically this will be {@link android.content.Intent#ACTION_VIEW} 
+	 * with an appropriate Uri for your content, but any Intent will work here as long as it 
+	 * triggers the desired action within your Activity.
+	 * @param profile 
+	 */
+	private void setupShortcut(VpnProfile profile) {
+		// First, set up the shortcut intent.  For this example, we simply create an intent that
+		// will bring us directly back to this activity.  A more typical implementation would use a 
+		// data Uri in order to display a more specific result, or a custom action in order to 
+		// launch a specific operation.
+
+		Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
+		shortcutIntent.setClass(this, LaunchVPN.class);
+		shortcutIntent.putExtra(EXTRA_KEY,profile.getUUID().toString());
+
+		// Then, set up the container intent (the response to the caller)
+
+		Intent intent = new Intent();
+		intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+		intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, profile.getName());
+		Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
+				this,  R.drawable.icon);
+		intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
+
+		// Now, return the result to the launcher
+
+		setResult(RESULT_OK, intent);
+	}
+
 
 	@Override
 	public void onItemClick(AdapterView<?> parent, View view, int position,
 			long id) {
-		 String profilename = ((TextView) view).getText().toString();
-		 
-		 VpnProfile profile = mPM.getProfileByName(profilename);
-
-	      // if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {	
-	            setupShortcut(profile);
-	            finish();
-	            return;
-	    //    }
-		 
+		String profilename = ((TextView) view).getText().toString();
+
+		VpnProfile profile = mPM.getProfileByName(profilename);
+
+		// if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {	
+		setupShortcut(profile);
+		finish();
+		return;
+		//    }
+
 	}
-	
+
 	private void askForPW(final String type) {
 
 		final EditText entry = new EditText(this);
@@ -243,16 +244,21 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 	@Override
 	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 		super.onActivityResult(requestCode, resultCode, data);
-		
-		if(requestCode==START_VPN_PROFILE && resultCode == Activity.RESULT_OK) {
-			
-			if(mSelectedProfile.needUserPWInput()!=null) {
-				askForPW(mSelectedProfile.needUserPWInput());
-			} else {
-				new startOpenVpnThread().start();
-			}
 
-		} 
+		if(requestCode==START_VPN_PROFILE) {
+			if(resultCode == Activity.RESULT_OK) {
+
+				if(mSelectedProfile.needUserPWInput()!=null) {
+					askForPW(mSelectedProfile.needUserPWInput());
+				} else {
+					new startOpenVpnThread().start();
+				}
+
+			} else if (resultCode == Activity.RESULT_CANCELED) {
+				// User does want us to start, so we just vanish
+				finish();
+			}
+		}
 	}
 
 	void showConfigErrorDialog(int vpnok) {
@@ -262,10 +268,10 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 		d.setPositiveButton(android.R.string.ok, null);
 		d.show();
 	}
-	
+
 	void launchVPN () {
-		
-		
+
+
 		int vpnok = mSelectedProfile.checkProfile();
 		if(vpnok!= R.string.no_error_found) {
 			showConfigErrorDialog(vpnok);
@@ -276,13 +282,17 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 
 		if (intent != null) {
 			// Start the query
-			startActivityForResult(intent, START_VPN_PROFILE);
+			try {
+				startActivityForResult(intent, START_VPN_PROFILE);
+			} catch (ActivityNotFoundException ane){
+				Toast.makeText(this, "Your image does not support the VPNService API,sorry :(", Toast.LENGTH_LONG);
+			}
 		} else {
 			onActivityResult(START_VPN_PROFILE, Activity.RESULT_OK, null);
 		}
-		
+
 	}
-	
+
 	private class startOpenVpnThread extends Thread {
 
 		@Override
@@ -305,5 +315,5 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
 		}
 	}
 
-	
+
 }
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java
index ea6c4926..86bd3665 100644
--- a/src/de/blinkt/openvpn/OpenVPN.java
+++ b/src/de/blinkt/openvpn/OpenVPN.java
@@ -100,8 +100,7 @@ public class OpenVPN {
 	
 	public static int openTunDevice() {
 		Log.d(TAG,"Opening tun device");
-		ParcelFileDescriptor pfd = mOpenVpnService.openTun();
-		return pfd.detachFd();
+		return mOpenVpnService.openTun();
 	}
 	//! Dummy method being called to force loading of JNI Libraries
 	public static void foo() {	}
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
index 02e5dc46..19f8d7e5 100644
--- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java
+++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
@@ -1,10 +1,13 @@
 package de.blinkt.openvpn;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.DatagramSocket;
 import java.util.Vector;
 
 import android.net.LocalSocket;
+import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
 public class OpenVpnManagementThread implements Runnable {
@@ -12,11 +15,14 @@ public class OpenVpnManagementThread implements Runnable {
 	private static final String TAG = "openvpn";
 	private LocalSocket mSocket;
 	private VpnProfile mProfile;
+	private OpenVpnService mOpenVPNService;
+	
 private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManagementThread>();
 	
-	public OpenVpnManagementThread(VpnProfile profile, LocalSocket mgmtsocket) {
+	public OpenVpnManagementThread(VpnProfile profile, LocalSocket mgmtsocket, OpenVpnService openVpnService) {
 		mProfile = profile;
 		mSocket = mgmtsocket;
+		mOpenVPNService = openVpnService;
 	}
 
 
@@ -102,6 +108,8 @@ private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManageme
 				processPWCommand(argument);
 			} else if (cmd.equals("HOLD")) {
 				managmentCommand("hold release\n");
+			} else if (cmd.equals("PROTECT-FD")) {
+				protectFD(argument);
 			}
 		}
         Log.i(TAG, "Got unrecognized command" + command);
@@ -109,6 +117,17 @@ private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManageme
 	}
 
 
+	private void protectFD(String argument) {
+		try {
+			FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
+			
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+	}
+
+
 	private void processPWCommand(String argument) {
 		//argument has the form 	Need 'Private Key' password
 		int p1 =argument.indexOf('\'');
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index 442fd94c..076fe7b5 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -33,8 +33,6 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
 	Handler mHandler;
 	private Thread mServiceThread;
 
-	private ParcelFileDescriptor mInterface;
-
 	private Vector<String> mDnslist=new Vector<String>();
 
 	private VpnProfile mProfile;
@@ -159,12 +157,12 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
 
 		if(mgmtsocket!=null) {
 			// start a Thread that handles incoming messages of the managment socket
-			mSocketManager = new OpenVpnManagementThread(mProfile,mgmtsocket);
+			mSocketManager = new OpenVpnManagementThread(mProfile,mgmtsocket,this);
 			mSocketManagerThread = new Thread(mSocketManager,"OpenVPNMgmtThread");
 			mSocketManagerThread.start();
 		}
 
-		return START_STICKY;
+		return START_NOT_STICKY;
 	}
 
 
@@ -191,7 +189,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
 
 
 
-	public ParcelFileDescriptor openTun() {
+	public int openTun() {
 		Builder builder = new Builder();
 
 		builder.addAddress(mLocalIP.mIp, mLocalIP.len);
@@ -223,8 +221,15 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
 		Intent intent = new Intent(getBaseContext(),LogWindow.class);
 		PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
 		builder.setConfigureIntent(startLW);
-		mInterface = builder.establish();
-		return mInterface;
+		try {
+			ParcelFileDescriptor pfd = builder.establish();
+			return pfd.detachFd();
+		} catch (Exception e) {
+			OpenVPN.logMessage(0, "", getString(R.string.tun_open_error));
+			OpenVPN.logMessage(0, "", getString(R.string.error) + e.getLocalizedMessage());
+			OpenVPN.logMessage(0, "", getString(R.string.tun_error_helpful));
+			return -1;
+		}
 
 	}
 
diff --git a/src/de/blinkt/openvpn/Settings_Obscure.java b/src/de/blinkt/openvpn/Settings_Obscure.java
index d7bce9ad..65d1c400 100644
--- a/src/de/blinkt/openvpn/Settings_Obscure.java
+++ b/src/de/blinkt/openvpn/Settings_Obscure.java
@@ -63,12 +63,14 @@ public class Settings_Obscure extends PreferenceFragment implements OnPreference
 		mProfile.mVerb = mLogverbosity.getValue();
 	}
 
+	
 	@Override
 	public boolean onPreferenceChange(Preference preference, Object newValue) {
 		if(preference==mLogverbosity) {
 			mLogverbosity.setDefaultValue(newValue);
-			// Does not refresh otherwise
-			mLogverbosity.setSummary("%s");
+			//This is idiotic. 
+			int i =Integer.parseInt((String) newValue);
+			mLogverbosity.setSummary(mLogverbosity.getEntries()[i]);
 		}
 			
 		return true;
diff --git a/src/de/blinkt/openvpn/VPNProfileList.java b/src/de/blinkt/openvpn/VPNProfileList.java
index 42c881a8..8565f460 100644
--- a/src/de/blinkt/openvpn/VPNProfileList.java
+++ b/src/de/blinkt/openvpn/VPNProfileList.java
@@ -2,38 +2,90 @@ package de.blinkt.openvpn;
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.ListFragment;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
+import android.view.ActionMode;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ArrayAdapter;
 import android.widget.EditText;
+import android.widget.ListView;
 import android.widget.Toast;
-import de.blinkt.openvpn.VPNConfigPreference.VpnPreferencesClickListener;
 
-public class VPNProfileList extends PreferenceFragment implements  VpnPreferencesClickListener {
+public class VPNProfileList extends ListFragment {
 	private static final int MENU_ADD_PROFILE = Menu.FIRST;
 
 	private static final int START_VPN_CONFIG = 92;
 
 
-	private VpnProfile mSelectedVPN;
+	private ArrayAdapter<VpnProfile> mArrayadapter;
 
+	protected Object mActionMode;
+
+	protected VpnProfile mEditProfile=null;
+
+	
+	
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
-		addPreferencesFromResource(R.xml.vpn_profile_list);
 		setHasOptionsMenu(true);
-		refreshList();
 		// Debug load JNI
 		OpenVPN.foo();
 	}
 
+	@Override
+	public void onActivityCreated(Bundle savedInstanceState) {
+		super.onActivityCreated(savedInstanceState);
+		ListView lv = getListView();
+		lv.setOnItemLongClickListener(new OnItemLongClickListener() {
+
+			// Called when the user long-clicks on someView
+
+			@Override
+			public boolean onItemLongClick(AdapterView<?> parent, View view,
+					int position, long id) {
+		        if (mActionMode != null) {
+		            return false;
+		        }
+
+		        // Start the CAB using the ActionMode.Callback defined above
+		        mActionMode = getActivity().startActionMode(mActionModeCallback);
+				mEditProfile =(VpnProfile) getListAdapter().getItem(position);
+
+				//getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+		        //getListView().setSelection(position);
+		        return true;
+			}
+		});
+		
+		lv.setOnItemClickListener(new OnItemClickListener() {
+
+			@Override
+			public void onItemClick(AdapterView<?> parent, View view,
+					int position, long id) {
+				VpnProfile profile =(VpnProfile) getListAdapter().getItem(position);
+				startVPN(profile);
+			}
+		});
+		
+
+        if(getPM().getNumberOfProfiles() == 0) {
+        	getPM().loadVPNList(getActivity());
+        }
+		
+		mArrayadapter = new ArrayAdapter<VpnProfile>(getActivity(),android.R.layout.simple_list_item_activated_1);
+		mArrayadapter.addAll(getPM().getProfiles());
+		setListAdapter(mArrayadapter);
+	}
 
 	@Override
 	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@@ -56,7 +108,27 @@ public class VPNProfileList extends PreferenceFragment implements  VpnPreference
 		}
 	}
 
+	private void askProfileRemoval() {
+		AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
+		dialog.setTitle("Confirm deletion");
+		dialog.setMessage(getString(R.string.remove_vpn_query, mEditProfile.mName));
+
+		dialog.setPositiveButton(android.R.string.yes,
+				new DialogInterface.OnClickListener() {
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				removeProfile(mEditProfile);
+			}
+
+		});
+		dialog.setNegativeButton(android.R.string.no,null);
+		dialog.create().show();
+	}
 
+	protected void removeProfile(VpnProfile profile) {
+		mArrayadapter.remove(profile);
+		
+	}
 
 	private void onAddProfileClicked() {
 		Context context = getActivity();
@@ -78,7 +150,6 @@ public class VPNProfileList extends PreferenceFragment implements  VpnPreference
 					if (getPM().getProfileByName(name)==null) {
 						VpnProfile profile = new VpnProfile(name);
 						addProfile(profile);
-						refreshList();
 					} else {
 						Toast.makeText(getActivity(), R.string.duplicate_profile_name, Toast.LENGTH_LONG).show();
 					}
@@ -102,58 +173,17 @@ public class VPNProfileList extends PreferenceFragment implements  VpnPreference
 		getPM().addProfile(profile);
 		getPM().saveProfileList(getActivity());
 		getPM().saveProfile(getActivity(),profile);
-
+		mArrayadapter.add(profile);
 	}
 
 
 
 
 
-	public void refreshList() {
-		PreferenceScreen plist = getPreferenceScreen();
-		if (plist != null) {
-			plist.removeAll(); 
-			getPM().loadVPNList(getActivity());
-
-			for (VpnProfile vpnprofile: getPM().getProfiles()) {
-
-				String profileuuid = vpnprofile.getUUID().toString();
-
-
-				VPNConfigPreference vpref = new VPNConfigPreference(this);
-				vpref.setKey(profileuuid);
-				vpref.setTitle(vpnprofile.getName());
-				vpref.setPersistent(false);
-				vpref.setOnQuickSettingsClickListener(this);
-				plist.addPreference(vpref);
-			}
-
-
-		}
-	}
-
-
-
 	private ProfileManager getPM() {
 		return ProfileManager.getInstance();
 	}
 
-	@Override
-	public boolean onQuickSettingsClick(Preference preference) {
-		String key = preference.getKey();
-
-		VpnProfile vprofile = ProfileManager.get(key);
-
-		Intent vprefintent = new Intent(getActivity(),VPNPreferences.class)
-		.putExtra(getActivity().getPackageName() + ".profileUUID", vprofile.getUUID().toString());
-
-		startActivityForResult(vprefintent,START_VPN_CONFIG);
-		return true;
-	}
-
-
-
-
 
 	@Override
 	public void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -164,26 +194,69 @@ public class VPNProfileList extends PreferenceFragment implements  VpnPreference
 			VpnProfile profile = ProfileManager.get(configuredVPN);
 			getPM().saveProfile(getActivity(), profile);
 			// Name could be modified
-			refreshList();
+
 		}
 
 	}
 
 
+	private void editVPN(VpnProfile profile) {
 
-	@Override
-	public void onStartVPNClick(VPNConfigPreference preference) {
-		getPM();
-		// Query the System for permission 
-		mSelectedVPN = ProfileManager.get(preference.getKey());
+		Intent vprefintent = new Intent(getActivity(),VPNPreferences.class)
+		.putExtra(getActivity().getPackageName() + ".profileUUID", profile.getUUID().toString());
 
-		getPM().saveProfile(getActivity(), mSelectedVPN);
+		startActivityForResult(vprefintent,START_VPN_CONFIG);
+	}
+
+	private void startVPN(VpnProfile profile) {
+
+		getPM().saveProfile(getActivity(), profile);
 
 		Intent intent = new Intent(getActivity(),LaunchVPN.class);
-		intent.putExtra(LaunchVPN.EXTRA_KEY, mSelectedVPN.getUUID().toString());
+		intent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
 		intent.setAction(Intent.ACTION_MAIN);
 		startActivity(intent);
 		
 		getActivity().finish();
 	}
+
+	private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
+		@Override
+		public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+			MenuInflater inflater = mode.getMenuInflater();
+			inflater.inflate(R.menu.vpn_context, menu);
+			return true;
+		}
+
+		@Override
+		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+			return false;// Return false if nothing is done
+		}
+
+		@Override
+		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+		      switch (item.getItemId()) {
+	            case R.id.remove_vpn:
+	                askProfileRemoval();
+	                mode.finish(); // Action picked, so close the CAB
+	                return true;
+	            case R.id.connect_vpn:
+	            	startVPN(mEditProfile);
+	            	mode.finish();
+	            	return true;
+	            case R.id.edit_vpn:
+	            	editVPN(mEditProfile);
+	            	mode.finish();
+	            	return true;
+	            default:
+	                return false;
+	        }		}
+
+		@Override
+		public void onDestroyActionMode(ActionMode mode) {
+	        mActionMode = null;
+	        getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
+		}
+	};
+
 }
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 04b5927f..ba3d4535 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -422,7 +422,7 @@ public class VpnProfile implements  Serializable{
 		return intent;
 	}
 
-	public String getTemporaryPKCS12Password() {
+	private String getTemporaryPKCS12Password() {
 		if(mTempPKCS12Password!=null)
 			return mTempPKCS12Password;
 
@@ -550,6 +550,13 @@ public class VpnProfile implements  Serializable{
 			return mPassword;
 		}
 	}
+	
+	
+	// Used by the Array Adapter
+	@Override
+	public String toString() {
+		return mName;
+	}
 
 
 
-- 
cgit v1.2.3