summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn/fragments
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/blinkt/openvpn/fragments')
-rw-r--r--src/de/blinkt/openvpn/fragments/AboutFragment.java60
-rw-r--r--src/de/blinkt/openvpn/fragments/FaqFragment.java43
-rw-r--r--src/de/blinkt/openvpn/fragments/FileSelectionFragment.java265
-rw-r--r--src/de/blinkt/openvpn/fragments/GeneralSettings.java31
-rw-r--r--src/de/blinkt/openvpn/fragments/InlineFileTab.java66
-rw-r--r--src/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java54
-rw-r--r--src/de/blinkt/openvpn/fragments/SendDumpFragment.java94
-rw-r--r--src/de/blinkt/openvpn/fragments/Settings_Authentication.java183
-rw-r--r--src/de/blinkt/openvpn/fragments/Settings_Basic.java336
-rw-r--r--src/de/blinkt/openvpn/fragments/Settings_IP.java129
-rw-r--r--src/de/blinkt/openvpn/fragments/Settings_Obscure.java115
-rw-r--r--src/de/blinkt/openvpn/fragments/Settings_Routing.java73
-rw-r--r--src/de/blinkt/openvpn/fragments/ShowConfigFragment.java89
-rw-r--r--src/de/blinkt/openvpn/fragments/VPNProfileList.java320
14 files changed, 1858 insertions, 0 deletions
diff --git a/src/de/blinkt/openvpn/fragments/AboutFragment.java b/src/de/blinkt/openvpn/fragments/AboutFragment.java
new file mode 100644
index 00000000..a0ee9928
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/AboutFragment.java
@@ -0,0 +1,60 @@
+package de.blinkt.openvpn.fragments;
+
+import android.app.Fragment;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import de.blinkt.openvpn.R;
+
+public class AboutFragment extends Fragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v= inflater.inflate(R.layout.about, container, false);
+ TextView ver = (TextView) v.findViewById(R.id.version);
+
+ String version;
+ String name="Openvpn";
+ try {
+ PackageInfo packageinfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
+ version = packageinfo.versionName;
+ name = getString(R.string.app);
+ } catch (NameNotFoundException e) {
+ version = "error fetching version";
+ }
+
+
+ ver.setText(getString(R.string.version_info,name,version));
+
+ TextView paypal = (TextView) v.findViewById(R.id.donatestring);
+
+ String donatetext = getActivity().getString(R.string.donatewithpaypal);
+ Spanned htmltext = Html.fromHtml(donatetext);
+ paypal.setText(htmltext);
+ paypal.setMovementMethod(LinkMovementMethod.getInstance());
+
+ TextView translation = (TextView) v.findViewById(R.id.translation);
+
+ // Don't print a text for myself
+ if ( getString(R.string.translationby).contains("Arne Schwabe"))
+ translation.setText("");
+ else
+ translation.setText(R.string.translationby);
+ return v;
+ }
+
+}
diff --git a/src/de/blinkt/openvpn/fragments/FaqFragment.java b/src/de/blinkt/openvpn/fragments/FaqFragment.java
new file mode 100644
index 00000000..459f2369
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/FaqFragment.java
@@ -0,0 +1,43 @@
+package de.blinkt.openvpn.fragments;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import de.blinkt.openvpn.R;
+
+public class FaqFragment extends Fragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v= inflater.inflate(R.layout.faq, container, false);
+
+ insertHtmlEntry(v,R.id.broken_images_faq,R.string.broken_images_faq);
+ insertHtmlEntry(v,R.id.faq_howto,R.string.faq_howto);
+ insertHtmlEntry(v, R.id.baterry_consumption, R.string.baterry_consumption);
+ insertHtmlEntry(v, R.id.faq_tethering, R.string.faq_tethering);
+
+ return v;
+
+
+
+ }
+
+ private void insertHtmlEntry (View v, int viewId, int stringId) {
+ TextView faqitem = (TextView) v.findViewById(viewId);
+ faqitem.setText(Html.fromHtml(getActivity().getString(stringId)));
+ faqitem.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+}
diff --git a/src/de/blinkt/openvpn/fragments/FileSelectionFragment.java b/src/de/blinkt/openvpn/fragments/FileSelectionFragment.java
new file mode 100644
index 00000000..15f7f709
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/FileSelectionFragment.java
@@ -0,0 +1,265 @@
+package de.blinkt.openvpn.fragments;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.TreeMap;
+
+import android.app.AlertDialog;
+import android.app.ListFragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+import de.blinkt.openvpn.FileSelect;
+import de.blinkt.openvpn.R;
+
+/**
+ * Activity para escolha de arquivos/diretorios.
+ *
+ * @author android
+ *
+ */
+public class FileSelectionFragment extends ListFragment {
+
+ private static final String ITEM_KEY = "key";
+ private static final String ITEM_IMAGE = "image";
+ private static final String ROOT = "/";
+
+
+ private List<String> path = null;
+ private TextView myPath;
+ private ArrayList<HashMap<String, Object>> mList;
+
+ private Button selectButton;
+
+
+ private String parentPath;
+ private String currentPath = ROOT;
+
+
+ private String[] formatFilter = null;
+
+ private File selectedFile;
+ private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>();
+ private String mStartPath;
+ private CheckBox mInlineImport;
+ private Button mClearButton;
+ private boolean mHideImport=false;
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.file_dialog_main, container,false);
+
+ myPath = (TextView) v.findViewById(R.id.path);
+
+ mInlineImport = (CheckBox) v.findViewById(R.id.doinline);
+
+ if(mHideImport== true) {
+ mInlineImport.setVisibility(View.GONE);
+ mInlineImport.setChecked(false);
+ }
+
+
+
+ selectButton = (Button) v.findViewById(R.id.fdButtonSelect);
+ selectButton.setEnabled(false);
+ selectButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (selectedFile != null) {
+ if(mInlineImport.isChecked())
+
+ ((FileSelect) getActivity()).importFile(selectedFile.getPath());
+ else
+ ((FileSelect) getActivity()).setFile(selectedFile.getPath());
+ }
+ }
+ });
+
+ mClearButton = (Button) v.findViewById(R.id.fdClear);
+ mClearButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ ((FileSelect) getActivity()).clearData();
+ }
+ });
+ if(!((FileSelect) getActivity()).showClear()) {
+ mClearButton.setVisibility(View.GONE);
+ mClearButton.setEnabled(false);
+ }
+
+
+
+
+ return v;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mStartPath = ((FileSelect) getActivity()).getSelectPath();
+ getDir(mStartPath);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ private void getDir(String dirPath) {
+
+ boolean useAutoSelection = dirPath.length() < currentPath.length();
+
+ Integer position = lastPositions.get(parentPath);
+
+ getDirImpl(dirPath);
+
+ if (position != null && useAutoSelection) {
+ getListView().setSelection(position);
+ }
+
+ }
+
+ /**
+ * Monta a estrutura de arquivos e diretorios filhos do diretorio fornecido.
+ *
+ * @param dirPath
+ * Diretorio pai.
+ */
+ private void getDirImpl(final String dirPath) {
+
+ currentPath = dirPath;
+
+ final List<String> item = new ArrayList<String>();
+ path = new ArrayList<String>();
+ mList = new ArrayList<HashMap<String, Object>>();
+
+ File f = new File(currentPath);
+ File[] files = f.listFiles();
+ if (files == null) {
+ currentPath = ROOT;
+ f = new File(currentPath);
+ files = f.listFiles();
+ }
+
+ myPath.setText(getText(R.string.location) + ": " + currentPath);
+
+ if (!currentPath.equals(ROOT)) {
+
+ item.add(ROOT);
+ addItem(ROOT, R.drawable.folder);
+ path.add(ROOT);
+
+ item.add("../");
+ addItem("../", R.drawable.folder);
+ path.add(f.getParent());
+ parentPath = f.getParent();
+
+ }
+
+ TreeMap<String, String> dirsMap = new TreeMap<String, String>();
+ TreeMap<String, String> dirsPathMap = new TreeMap<String, String>();
+ TreeMap<String, String> filesMap = new TreeMap<String, String>();
+ TreeMap<String, String> filesPathMap = new TreeMap<String, String>();
+ for (File file : files) {
+ if (file.isDirectory()) {
+ String dirName = file.getName();
+ dirsMap.put(dirName, dirName);
+ dirsPathMap.put(dirName, file.getPath());
+ } else {
+ final String fileName = file.getName();
+ final String fileNameLwr = fileName.toLowerCase(Locale.getDefault());
+ // se ha um filtro de formatos, utiliza-o
+ if (formatFilter != null) {
+ boolean contains = false;
+ for (int i = 0; i < formatFilter.length; i++) {
+ final String formatLwr = formatFilter[i].toLowerCase(Locale.getDefault());
+ if (fileNameLwr.endsWith(formatLwr)) {
+ contains = true;
+ break;
+ }
+ }
+ if (contains) {
+ filesMap.put(fileName, fileName);
+ filesPathMap.put(fileName, file.getPath());
+ }
+ // senao, adiciona todos os arquivos
+ } else {
+ filesMap.put(fileName, fileName);
+ filesPathMap.put(fileName, file.getPath());
+ }
+ }
+ }
+ item.addAll(dirsMap.tailMap("").values());
+ item.addAll(filesMap.tailMap("").values());
+ path.addAll(dirsPathMap.tailMap("").values());
+ path.addAll(filesPathMap.tailMap("").values());
+
+ SimpleAdapter fileList = new SimpleAdapter(getActivity(), mList, R.layout.file_dialog_row, new String[] {
+ ITEM_KEY, ITEM_IMAGE }, new int[] { R.id.fdrowtext, R.id.fdrowimage });
+
+ for (String dir : dirsMap.tailMap("").values()) {
+ addItem(dir, R.drawable.folder);
+ }
+
+ for (String file : filesMap.tailMap("").values()) {
+ addItem(file, R.drawable.file);
+ }
+
+ fileList.notifyDataSetChanged();
+
+ setListAdapter(fileList);
+
+ }
+
+ private void addItem(String fileName, int imageId) {
+ HashMap<String, Object> item = new HashMap<String, Object>();
+ item.put(ITEM_KEY, fileName);
+ item.put(ITEM_IMAGE, imageId);
+ mList.add(item);
+ }
+
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+
+ File file = new File(path.get(position));
+
+ if (file.isDirectory()) {
+ selectButton.setEnabled(false);
+
+ if (file.canRead()) {
+ lastPositions.put(currentPath, position);
+ getDir(path.get(position));
+ } else {
+ new AlertDialog.Builder(getActivity()).setIcon(R.drawable.icon)
+ .setTitle("[" + file.getName() + "] " + getText(R.string.cant_read_folder))
+ .setPositiveButton("OK", null).show();
+ }
+ } else {
+ selectedFile = file;
+ v.setSelected(true);
+ selectButton.setEnabled(true);
+ }
+ }
+
+ public void setNoInLine() {
+ mHideImport=true;
+
+ }
+
+}
diff --git a/src/de/blinkt/openvpn/fragments/GeneralSettings.java b/src/de/blinkt/openvpn/fragments/GeneralSettings.java
new file mode 100644
index 00000000..4ac0a8ac
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/GeneralSettings.java
@@ -0,0 +1,31 @@
+package de.blinkt.openvpn.fragments;
+import java.io.File;
+
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import de.blinkt.openvpn.R;
+
+public class GeneralSettings extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.general_settings);
+ Preference loadtun = findPreference("loadTunModule");
+ if(!isTunModuleAvailable())
+ loadtun.setEnabled(false);
+ }
+
+ private boolean isTunModuleAvailable() {
+ // Check if the tun module exists on the file system
+ if(new File("/system/lib/modules/tun.ko").length() > 10)
+ return true;
+ return false;
+ }
+
+
+ } \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/InlineFileTab.java b/src/de/blinkt/openvpn/fragments/InlineFileTab.java
new file mode 100644
index 00000000..6b19b75a
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/InlineFileTab.java
@@ -0,0 +1,66 @@
+package de.blinkt.openvpn.fragments;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import de.blinkt.openvpn.FileSelect;
+import de.blinkt.openvpn.R;
+
+public class InlineFileTab extends Fragment
+{
+
+ private static final int MENU_SAVE = 0;
+ private EditText mInlineData;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mInlineData.setText(((FileSelect)getActivity()).getInlineData());
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState)
+ {
+
+ View v = inflater.inflate(R.layout.file_dialog_inline, container, false);
+ mInlineData =(EditText) v.findViewById(R.id.inlineFileData);
+ return v;
+ }
+
+ public void setData(String data) {
+ if(mInlineData!=null)
+ mInlineData.setText(data);
+
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ menu.add(0, MENU_SAVE, 0, "Use inline data")
+ .setIcon(android.R.drawable.ic_menu_save)
+ .setAlphabeticShortcut('u')
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
+ | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if(item.getItemId()==MENU_SAVE){
+ ((FileSelect)getActivity()).saveInlineData(mInlineData.getText().toString());
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java b/src/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java
new file mode 100644
index 00000000..ae9f2004
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java
@@ -0,0 +1,54 @@
+package de.blinkt.openvpn.fragments;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ProfileManager;
+
+public abstract class OpenVpnPreferencesFragment extends PreferenceFragment {
+
+ protected VpnProfile mProfile;
+
+ protected abstract void loadSettings();
+ protected abstract void saveSettings();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID");
+ mProfile = ProfileManager.get(getActivity(),profileUUID);
+ getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName()));
+
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ saveSettings();
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if(savedInstanceState!=null) {
+ String profileUUID=savedInstanceState.getString(VpnProfile.EXTRA_PROFILEUUID);
+ mProfile = ProfileManager.get(getActivity(),profileUUID);
+ loadSettings();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ // TODO Auto-generated method stub
+ super.onStop();
+ }
+
+ @Override
+ public void onSaveInstanceState (Bundle outState) {
+ super.onSaveInstanceState(outState);
+ saveSettings();
+ outState.putString(VpnProfile.EXTRA_PROFILEUUID, mProfile.getUUIDString());
+ }
+}
diff --git a/src/de/blinkt/openvpn/fragments/SendDumpFragment.java b/src/de/blinkt/openvpn/fragments/SendDumpFragment.java
new file mode 100644
index 00000000..020379ef
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/SendDumpFragment.java
@@ -0,0 +1,94 @@
+package de.blinkt.openvpn.fragments;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.core.OpenVPN;
+
+public class SendDumpFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View v = inflater.inflate(R.layout.fragment_senddump, container, false);
+ v.findViewById(R.id.senddump).setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ emailMiniDumps();
+ }
+ });
+ return v;
+ }
+
+ public void emailMiniDumps()
+ {
+ //need to "send multiple" to get more than one attachment
+ final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
+ emailIntent.setType("*/*");
+ emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
+ new String[]{"Arne Schwabe <arne@rfc2549.org>"});
+
+ String version;
+ String name="ics-openvpn";
+ try {
+ PackageInfo packageinfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
+ version = packageinfo.versionName;
+ name = packageinfo.applicationInfo.name;
+ } catch (NameNotFoundException e) {
+ version = "error fetching version";
+ }
+
+
+ emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format("%s %s Minidump",name,version));
+
+ emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe the issue you have experienced");
+
+ ArrayList<Uri> uris = new ArrayList<Uri>();
+
+ File ldump = getLastestDump(getActivity());
+ if(ldump==null) {
+ OpenVPN.logError("No Minidump found!");
+ }
+
+ uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName()));
+ uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName() + ".log"));
+
+ emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
+ startActivity(emailIntent);
+ }
+
+ static public File getLastestDump(Context c) {
+ long newestDumpTime=0;
+ File newestDumpFile=null;
+
+ for(File f:c.getCacheDir().listFiles()) {
+ if(!f.getName().endsWith(".dmp"))
+ continue;
+
+ if (newestDumpTime < f.lastModified()) {
+ newestDumpTime = f.lastModified();
+ newestDumpFile=f;
+ }
+ }
+ // Ignore old dumps
+ //if(System.currentTimeMillis() - 48 * 60 * 1000 > newestDumpTime )
+ //return null;
+
+ return newestDumpFile;
+ }
+}
diff --git a/src/de/blinkt/openvpn/fragments/Settings_Authentication.java b/src/de/blinkt/openvpn/fragments/Settings_Authentication.java
new file mode 100644
index 00000000..9ec77f35
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/Settings_Authentication.java
@@ -0,0 +1,183 @@
+package de.blinkt.openvpn.fragments;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.SwitchPreference;
+import android.util.Pair;
+import de.blinkt.openvpn.FileSelect;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.RemoteCNPreference;
+import de.blinkt.openvpn.VpnProfile;
+
+
+public class Settings_Authentication extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener, OnPreferenceClickListener {
+ private static final int SELECT_TLS_FILE = 23223232;
+ private CheckBoxPreference mExpectTLSCert;
+ private CheckBoxPreference mCheckRemoteCN;
+ private RemoteCNPreference mRemoteCN;
+ private ListPreference mTLSAuthDirection;
+ private Preference mTLSAuthFile;
+ private SwitchPreference mUseTLSAuth;
+ private EditTextPreference mCipher;
+ private String mTlsAuthFileData;
+ private EditTextPreference mAuth;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.vpn_authentification);
+
+ mExpectTLSCert = (CheckBoxPreference) findPreference("remoteServerTLS");
+ mCheckRemoteCN = (CheckBoxPreference) findPreference("checkRemoteCN");
+ mRemoteCN = (RemoteCNPreference) findPreference("remotecn");
+ mRemoteCN.setOnPreferenceChangeListener(this);
+
+ mUseTLSAuth = (SwitchPreference) findPreference("useTLSAuth" );
+ mTLSAuthFile = findPreference("tlsAuthFile");
+ mTLSAuthDirection = (ListPreference) findPreference("tls_direction");
+
+
+ mTLSAuthFile.setOnPreferenceClickListener(this);
+
+ mCipher =(EditTextPreference) findPreference("cipher");
+ mCipher.setOnPreferenceChangeListener(this);
+
+ mAuth =(EditTextPreference) findPreference("auth");
+ mAuth.setOnPreferenceChangeListener(this);
+
+ loadSettings();
+
+ }
+
+ @Override
+ protected void loadSettings() {
+
+ mExpectTLSCert.setChecked(mProfile.mExpectTLSCert);
+ mCheckRemoteCN.setChecked(mProfile.mCheckRemoteCN);
+ mRemoteCN.setDN(mProfile.mRemoteCN);
+ mRemoteCN.setAuthType(mProfile.mX509AuthType);
+ onPreferenceChange(mRemoteCN,
+ new Pair<Integer, String>(mProfile.mX509AuthType, mProfile.mRemoteCN));
+
+ mUseTLSAuth.setChecked(mProfile.mUseTLSAuth);
+ mTlsAuthFileData= mProfile.mTLSAuthFilename;
+ setTlsAuthSummary(mTlsAuthFileData);
+ mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection);
+ mCipher.setText(mProfile.mCipher);
+ onPreferenceChange(mCipher, mProfile.mCipher);
+ mAuth.setText(mProfile.mAuth);
+ onPreferenceChange(mAuth, mProfile.mAuth);
+ }
+
+ @Override
+ protected void saveSettings() {
+ mProfile.mExpectTLSCert=mExpectTLSCert.isChecked();
+ mProfile.mCheckRemoteCN=mCheckRemoteCN.isChecked();
+ mProfile.mRemoteCN=mRemoteCN.getCNText();
+ mProfile.mX509AuthType=mRemoteCN.getAuthtype();
+
+ mProfile.mUseTLSAuth = mUseTLSAuth.isChecked();
+ mProfile.mTLSAuthFilename = mTlsAuthFileData;
+
+ if(mTLSAuthDirection.getValue()==null)
+ mProfile.mTLSAuthDirection=null;
+ else
+ mProfile.mTLSAuthDirection = mTLSAuthDirection.getValue().toString();
+
+ if(mCipher.getText()==null)
+ mProfile.mCipher=null;
+ else
+ mProfile.mCipher = mCipher.getText();
+
+ if(mAuth.getText()==null)
+ mProfile.mAuth = null;
+ else
+ mProfile.mAuth = mAuth.getText();
+
+ }
+
+
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if(preference==mRemoteCN) {
+ @SuppressWarnings("unchecked")
+ int authtype = ((Pair<Integer, String>) newValue).first;
+ @SuppressWarnings("unchecked")
+ String dn = ((Pair<Integer, String>) newValue).second;
+
+ if ("".equals(dn))
+ preference.setSummary(getX509String(VpnProfile.X509_VERIFY_TLSREMOTE_RDN, mProfile.mServerName));
+ else
+ preference.setSummary(getX509String(authtype,dn));
+
+ } else if (preference == mCipher || preference == mAuth) {
+ preference.setSummary((CharSequence) newValue);
+ }
+ return true;
+ }
+ private CharSequence getX509String(int authtype, String dn) {
+ String ret ="";
+ switch (authtype) {
+ case VpnProfile.X509_VERIFY_TLSREMOTE:
+ case VpnProfile.X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING:
+ ret+="tls-remote ";
+ break;
+
+ case VpnProfile.X509_VERIFY_TLSREMOTE_DN:
+ ret="dn: ";
+ break;
+
+ case VpnProfile.X509_VERIFY_TLSREMOTE_RDN:
+ ret="rdn: ";
+ break;
+
+ case VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX:
+ ret="rdn prefix: ";
+ break;
+ }
+ return ret + dn;
+ }
+
+ void startFileDialog() {
+ Intent startFC = new Intent(getActivity(),FileSelect.class);
+ startFC.putExtra(FileSelect.START_DATA, Environment.getExternalStorageDirectory().getPath());
+
+ startActivityForResult(startFC,SELECT_TLS_FILE);
+ }
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startFileDialog();
+ return true;
+
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if(requestCode==SELECT_TLS_FILE && resultCode == Activity.RESULT_OK){
+ String result = data.getStringExtra(FileSelect.RESULT_DATA);
+ mTlsAuthFileData=result;
+ setTlsAuthSummary(result);
+
+ }
+ }
+
+ private void setTlsAuthSummary(String result) {
+ if(result==null) result = getString(R.string.no_certificate);
+ if(result.startsWith(VpnProfile.INLINE_TAG))
+ mTLSAuthFile.setSummary(R.string.inline_file_data);
+ else
+ mTLSAuthFile.setSummary(result);
+ }
+} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/Settings_Basic.java b/src/de/blinkt/openvpn/fragments/Settings_Basic.java
new file mode 100644
index 00000000..430ae4ef
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/Settings_Basic.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.blinkt.openvpn.fragments;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Fragment;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+import de.blinkt.openvpn.FileSelect;
+import de.blinkt.openvpn.FileSelectLayout;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.R.id;
+import de.blinkt.openvpn.core.ProfileManager;
+
+public class Settings_Basic extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback {
+ private static final int CHOOSE_FILE_OFFSET = 1000;
+ private static final int UPDATE_ALIAS = 20;
+
+
+
+ private TextView mServerAddress;
+ private TextView mServerPort;
+ private FileSelectLayout mClientCert;
+ private FileSelectLayout mCaCert;
+ private FileSelectLayout mClientKey;
+ private TextView mAliasName;
+ private CheckBox mUseLzo;
+ private ToggleButton mTcpUdp;
+ private Spinner mType;
+ private FileSelectLayout mpkcs12;
+ private TextView mPKCS12Password;
+ private Handler mHandler;
+ private EditText mUserName;
+ private EditText mPassword;
+ private View mView;
+ private VpnProfile mProfile;
+ private EditText mProfileName;
+ private EditText mKeyPassword;
+
+ private SparseArray<FileSelectLayout> fileselects = new SparseArray<FileSelectLayout>();
+
+
+ private void addFileSelectLayout (FileSelectLayout fsl) {
+ int i = fileselects.size() + CHOOSE_FILE_OFFSET;
+ fileselects.put(i, fsl);
+ fsl.setFragment(this,i);
+ }
+
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String profileuuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID");
+ mProfile=ProfileManager.get(profileuuid);
+ getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName()));
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+
+ mView = inflater.inflate(R.layout.basic_settings,container,false);
+
+ mProfileName = (EditText) mView.findViewById(R.id.profilename);
+ mServerAddress = (TextView) mView.findViewById(R.id.address);
+ mServerPort = (TextView) mView.findViewById(R.id.port);
+ mClientCert = (FileSelectLayout) mView.findViewById(R.id.certselect);
+ mClientKey = (FileSelectLayout) mView.findViewById(R.id.keyselect);
+ mCaCert = (FileSelectLayout) mView.findViewById(R.id.caselect);
+ mpkcs12 = (FileSelectLayout) mView.findViewById(R.id.pkcs12select);
+ mUseLzo = (CheckBox) mView.findViewById(R.id.lzo);
+ mTcpUdp = (ToggleButton) mView.findViewById(id.tcpudp);
+ mType = (Spinner) mView.findViewById(R.id.type);
+ mPKCS12Password = (TextView) mView.findViewById(R.id.pkcs12password);
+ mAliasName = (TextView) mView.findViewById(R.id.aliasname);
+
+ mUserName = (EditText) mView.findViewById(R.id.auth_username);
+ mPassword = (EditText) mView.findViewById(R.id.auth_password);
+ mKeyPassword = (EditText) mView.findViewById(R.id.key_password);
+
+
+
+ addFileSelectLayout(mCaCert);
+ addFileSelectLayout(mClientCert);
+ addFileSelectLayout(mClientKey);
+ addFileSelectLayout(mpkcs12);
+ mpkcs12.setBase64Encode();
+ mCaCert.setShowClear();
+
+ mType.setOnItemSelectedListener(this);
+
+ mView.findViewById(R.id.select_keystore_button).setOnClickListener(this);
+
+
+ if (mHandler == null) {
+ mHandler = new Handler(this);
+ }
+
+ return mView;
+ }
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ String profileuuid =getArguments().getString(getActivity().getPackageName() + ".profileUUID");
+ mProfile=ProfileManager.get(profileuuid);
+ loadPreferences();
+
+ }
+
+ @Override
+ public void onActivityResult(int request, int result, Intent data) {
+ if (result == Activity.RESULT_OK && request >= CHOOSE_FILE_OFFSET) {
+ String filedata = data.getStringExtra(FileSelect.RESULT_DATA);
+ FileSelectLayout fsl = fileselects.get(request);
+ fsl.setData(filedata);
+
+ savePreferences();
+
+ // Private key files may result in showing/hiding the private key password dialog
+ if(fsl==mClientKey) {
+ changeType(mType.getSelectedItemPosition());
+ }
+ }
+
+ }
+
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ if (parent == mType) {
+ changeType(position);
+ }
+ }
+ @Override
+ public void onPause() {
+ super.onPause();
+ savePreferences();
+ }
+
+
+
+ private void changeType(int type){
+ // hide everything
+ mView.findViewById(R.id.pkcs12).setVisibility(View.GONE);
+ mView.findViewById(R.id.certs).setVisibility(View.GONE);
+ mView.findViewById(R.id.statickeys).setVisibility(View.GONE);
+ mView.findViewById(R.id.keystore).setVisibility(View.GONE);
+ mView.findViewById(R.id.cacert).setVisibility(View.GONE);
+ mView.findViewById(R.id.userpassword).setVisibility(View.GONE);
+ mView.findViewById(R.id.key_password_layout).setVisibility(View.GONE);
+
+ // Fall through are by design
+ switch(type) {
+ case VpnProfile.TYPE_USERPASS_CERTIFICATES:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
+ case VpnProfile.TYPE_CERTIFICATES:
+ mView.findViewById(R.id.certs).setVisibility(View.VISIBLE);
+ mView.findViewById(R.id.cacert).setVisibility(View.VISIBLE);
+ if(mProfile.requireTLSKeyPassword())
+ mView.findViewById(R.id.key_password_layout).setVisibility(View.VISIBLE);
+ break;
+
+ case VpnProfile.TYPE_USERPASS_PKCS12:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
+ case VpnProfile.TYPE_PKCS12:
+ mView.findViewById(R.id.pkcs12).setVisibility(View.VISIBLE);
+ break;
+
+ case VpnProfile.TYPE_STATICKEYS:
+ mView.findViewById(R.id.statickeys).setVisibility(View.VISIBLE);
+ break;
+
+ case VpnProfile.TYPE_USERPASS_KEYSTORE:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
+ case VpnProfile.TYPE_KEYSTORE:
+ mView.findViewById(R.id.keystore).setVisibility(View.VISIBLE);
+ mView.findViewById(R.id.cacert).setVisibility(View.VISIBLE);
+ break;
+
+ case VpnProfile.TYPE_USERPASS:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
+ mView.findViewById(R.id.cacert).setVisibility(View.VISIBLE);
+ break;
+ }
+
+
+ }
+
+ private void loadPreferences() {
+ mProfileName.setText(mProfile.mName);
+ mClientCert.setData(mProfile.mClientCertFilename);
+ mClientKey.setData(mProfile.mClientKeyFilename);
+ mCaCert.setData(mProfile.mCaFilename);
+
+ mUseLzo.setChecked(mProfile.mUseLzo);
+ mServerPort.setText(mProfile.mServerPort);
+ mServerAddress.setText(mProfile.mServerName);
+ mTcpUdp.setChecked(mProfile.mUseUdp);
+ mType.setSelection(mProfile.mAuthenticationType);
+ mpkcs12.setData(mProfile.mPKCS12Filename);
+ mPKCS12Password.setText(mProfile.mPKCS12Password);
+ mUserName.setText(mProfile.mUsername);
+ mPassword.setText(mProfile.mPassword);
+ mKeyPassword.setText(mProfile.mKeyPassword);
+
+ setAlias();
+
+ }
+
+ void savePreferences() {
+
+ mProfile.mName = mProfileName.getText().toString();
+ mProfile.mCaFilename = mCaCert.getData();
+ mProfile.mClientCertFilename = mClientCert.getData();
+ mProfile.mClientKeyFilename = mClientKey.getData();
+
+ mProfile.mUseLzo = mUseLzo.isChecked();
+ mProfile.mServerPort =mServerPort.getText().toString();
+ mProfile.mServerName = mServerAddress.getText().toString();
+ mProfile.mUseUdp = mTcpUdp.isChecked();
+
+ mProfile.mAuthenticationType = mType.getSelectedItemPosition();
+ mProfile.mPKCS12Filename = mpkcs12.getData();
+ mProfile.mPKCS12Password = mPKCS12Password.getText().toString();
+
+ mProfile.mPassword = mPassword.getText().toString();
+ mProfile.mUsername = mUserName.getText().toString();
+ mProfile.mKeyPassword = mKeyPassword.getText().toString();
+
+ }
+
+
+ private void setAlias() {
+ if(mProfile.mAlias == null) {
+ mAliasName.setText(R.string.client_no_certificate);
+ } else {
+ mAliasName.setText(mProfile.mAlias);
+ }
+ }
+
+ public void showCertDialog () {
+ try {
+ KeyChain.choosePrivateKeyAlias(getActivity(),
+ new KeyChainAliasCallback() {
+
+ public void alias(String alias) {
+ // Credential alias selected. Remember the alias selection for future use.
+ mProfile.mAlias=alias;
+ mHandler.sendEmptyMessage(UPDATE_ALIAS);
+ }
+
+
+ },
+ new String[] {"RSA"}, // List of acceptable key types. null for any
+ null, // issuer, null for any
+ mProfile.mServerName, // host name of server requesting the cert, null if unavailable
+ -1, // port of server requesting the cert, -1 if unavailable
+ mProfile.mAlias); // alias to preselect, null if unavailable
+ } catch (ActivityNotFoundException anf) {
+ Builder ab = new AlertDialog.Builder(getActivity());
+ ab.setTitle(R.string.broken_image_cert_title);
+ ab.setMessage(R.string.broken_image_cert);
+ ab.setPositiveButton(android.R.string.ok, null);
+ ab.show();
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mView.findViewById(R.id.select_keystore_button)) {
+ showCertDialog();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ savePreferences();
+ if(mProfile!=null) {
+ outState.putString(getActivity().getPackageName() + "profileUUID", mProfile.getUUID().toString());
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ setAlias();
+ return true;
+ }
+
+
+}
diff --git a/src/de/blinkt/openvpn/fragments/Settings_IP.java b/src/de/blinkt/openvpn/fragments/Settings_IP.java
new file mode 100644
index 00000000..483397d0
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/Settings_IP.java
@@ -0,0 +1,129 @@
+package de.blinkt.openvpn.fragments;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceManager;
+import android.preference.SwitchPreference;
+import de.blinkt.openvpn.R;
+
+public class Settings_IP extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener {
+ private EditTextPreference mIPv4;
+ private EditTextPreference mIPv6;
+ private SwitchPreference mUsePull;
+ private CheckBoxPreference mOverrideDNS;
+ private EditTextPreference mSearchdomain;
+ private EditTextPreference mDNS1;
+ private EditTextPreference mDNS2;
+ private CheckBoxPreference mNobind;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+
+ // Make sure default values are applied. In a real app, you would
+ // want this in a shared function that is used to retrieve the
+ // SharedPreferences wherever they are needed.
+ PreferenceManager.setDefaultValues(getActivity(),
+ R.xml.vpn_ipsettings, false);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.vpn_ipsettings);
+ mIPv4 = (EditTextPreference) findPreference("ipv4_address");
+ mIPv6 = (EditTextPreference) findPreference("ipv6_address");
+ mUsePull = (SwitchPreference) findPreference("usePull");
+ mOverrideDNS = (CheckBoxPreference) findPreference("overrideDNS");
+ mSearchdomain =(EditTextPreference) findPreference("searchdomain");
+ mDNS1 = (EditTextPreference) findPreference("dns1");
+ mDNS2 = (EditTextPreference) findPreference("dns2");
+ mNobind = (CheckBoxPreference) findPreference("nobind");
+
+ mIPv4.setOnPreferenceChangeListener(this);
+ mIPv6.setOnPreferenceChangeListener(this);
+ mDNS1.setOnPreferenceChangeListener(this);
+ mDNS2.setOnPreferenceChangeListener(this);
+ mUsePull.setOnPreferenceChangeListener(this);
+ mOverrideDNS.setOnPreferenceChangeListener(this);
+ mSearchdomain.setOnPreferenceChangeListener(this);
+
+ loadSettings();
+ }
+
+ @Override
+ protected void loadSettings() {
+
+ mUsePull.setChecked(mProfile.mUsePull);
+ mIPv4.setText(mProfile.mIPv4Address);
+ mIPv6.setText(mProfile.mIPv6Address);
+ mDNS1.setText(mProfile.mDNS1);
+ mDNS2.setText(mProfile.mDNS2);
+ mOverrideDNS.setChecked(mProfile.mOverrideDNS);
+ mSearchdomain.setText(mProfile.mSearchDomain);
+ mNobind.setChecked(mProfile.mNobind);
+
+ // Sets Summary
+ onPreferenceChange(mIPv4, mIPv4.getText());
+ onPreferenceChange(mIPv6, mIPv6.getText());
+ onPreferenceChange(mDNS1, mDNS1.getText());
+ onPreferenceChange(mDNS2, mDNS2.getText());
+ onPreferenceChange(mSearchdomain, mSearchdomain.getText());
+
+ setDNSState();
+ }
+
+
+ @Override
+ protected void saveSettings() {
+ mProfile.mUsePull = mUsePull.isChecked();
+ mProfile.mIPv4Address = mIPv4.getText();
+ mProfile.mIPv6Address = mIPv6.getText();
+ mProfile.mDNS1 = mDNS1.getText();
+ mProfile.mDNS2 = mDNS2.getText();
+ mProfile.mOverrideDNS = mOverrideDNS.isChecked();
+ mProfile.mSearchDomain = mSearchdomain.getText();
+ mProfile.mNobind = mNobind.isChecked();
+
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference,
+ Object newValue) {
+ if(preference==mIPv4 || preference == mIPv6
+ || preference==mDNS1 || preference == mDNS2
+ || preference == mSearchdomain
+ )
+
+ preference.setSummary((String)newValue);
+
+ if(preference== mUsePull || preference == mOverrideDNS)
+ if(preference==mOverrideDNS) {
+ // Set so the function gets the right value
+ mOverrideDNS.setChecked((Boolean) newValue);
+ }
+ setDNSState();
+
+ saveSettings();
+ return true;
+ }
+
+ private void setDNSState() {
+ boolean enabled;
+ mOverrideDNS.setEnabled(mUsePull.isChecked());
+ if(!mUsePull.isChecked())
+ enabled =true;
+ else if (mOverrideDNS.isChecked())
+ enabled = true;
+ else
+ enabled = false;
+
+ mDNS1.setEnabled(enabled);
+ mDNS2.setEnabled(enabled);
+ mSearchdomain.setEnabled(enabled);
+
+
+ }
+
+
+ } \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/Settings_Obscure.java b/src/de/blinkt/openvpn/fragments/Settings_Obscure.java
new file mode 100644
index 00000000..03df51f2
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/Settings_Obscure.java
@@ -0,0 +1,115 @@
+package de.blinkt.openvpn.fragments;
+
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import de.blinkt.openvpn.R;
+
+public class Settings_Obscure extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener {
+ private CheckBoxPreference mUseRandomHostName;
+ private CheckBoxPreference mUseFloat;
+ private CheckBoxPreference mUseCustomConfig;
+ private EditTextPreference mCustomConfig;
+ private ListPreference mLogverbosity;
+ private CheckBoxPreference mPersistent;
+ private ListPreference mConnectretrymax;
+ private EditTextPreference mConnectretry;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.vpn_obscure);
+
+ mUseRandomHostName = (CheckBoxPreference) findPreference("useRandomHostname");
+ mUseFloat = (CheckBoxPreference) findPreference("useFloat");
+ mUseCustomConfig = (CheckBoxPreference) findPreference("enableCustomOptions");
+ mCustomConfig = (EditTextPreference) findPreference("customOptions");
+ mLogverbosity = (ListPreference) findPreference("verblevel");
+ mPersistent = (CheckBoxPreference) findPreference("usePersistTun");
+ mConnectretrymax = (ListPreference) findPreference("connectretrymax");
+ mConnectretry = (EditTextPreference) findPreference("connectretry");
+
+ mLogverbosity.setOnPreferenceChangeListener(this);
+ mLogverbosity.setSummary("%s");
+
+ mConnectretrymax.setOnPreferenceChangeListener(this);
+ mConnectretrymax.setSummary("%s");
+
+ mConnectretry.setOnPreferenceChangeListener(this);
+
+
+ loadSettings();
+
+ }
+
+ protected void loadSettings() {
+ mUseRandomHostName.setChecked(mProfile.mUseRandomHostname);
+ mUseFloat.setChecked(mProfile.mUseFloat);
+ mUseCustomConfig.setChecked(mProfile.mUseCustomConfig);
+ mCustomConfig.setText(mProfile.mCustomConfigOptions);
+ mPersistent.setChecked(mProfile.mPersistTun);
+
+ mLogverbosity.setValue(mProfile.mVerb);
+ onPreferenceChange(mLogverbosity, mProfile.mVerb);
+
+ mConnectretrymax.setValue(mProfile.mConnectRetryMax);
+ onPreferenceChange(mConnectretrymax, mProfile.mConnectRetryMax);
+
+ mConnectretry.setText(mProfile.mConnectRetry);
+ onPreferenceChange(mConnectretry, mProfile.mConnectRetry);
+ }
+
+
+ protected void saveSettings() {
+ mProfile.mUseRandomHostname = mUseRandomHostName.isChecked();
+ mProfile.mUseFloat = mUseFloat.isChecked();
+ mProfile.mUseCustomConfig = mUseCustomConfig.isChecked();
+ mProfile.mCustomConfigOptions = mCustomConfig.getText();
+ mProfile.mVerb = mLogverbosity.getValue();
+ mProfile.mConnectRetryMax = mConnectretrymax.getValue();
+ mProfile.mPersistTun = mPersistent.isChecked();
+ mProfile.mConnectRetry = mConnectretry.getText();
+ }
+
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if(preference==mLogverbosity) {
+ // Catch old version problem
+ if(newValue==null){
+ newValue="1";
+ }
+ mLogverbosity.setDefaultValue(newValue);
+ //This is idiotic.
+ int i =Integer.parseInt((String) newValue);
+
+ // verb >= 5 is not supported by the chooser
+ if(i < mLogverbosity.getEntries().length )
+ mLogverbosity.setSummary(mLogverbosity.getEntries()[i]);
+ else
+ mLogverbosity.setSummary(String.format("debug verbosity: %d",i));
+ } else if (preference == mConnectretrymax) {
+ if(newValue==null) {
+ newValue="5";
+ }
+ mConnectretrymax.setDefaultValue(newValue);
+
+ for(int i=0;i<mConnectretrymax.getEntryValues().length;i++){
+ if(mConnectretrymax.getEntryValues().equals(newValue))
+ mConnectretrymax.setSummary(mConnectretrymax.getEntries()[i]);
+ }
+
+ } else if (preference == mConnectretry) {
+ if(newValue==null || newValue=="")
+ newValue="5";
+ mConnectretry.setSummary(String.format("%s s" , newValue));
+ }
+
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/Settings_Routing.java b/src/de/blinkt/openvpn/fragments/Settings_Routing.java
new file mode 100644
index 00000000..63b54bf3
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/Settings_Routing.java
@@ -0,0 +1,73 @@
+package de.blinkt.openvpn.fragments;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import de.blinkt.openvpn.R;
+
+
+public class Settings_Routing extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener {
+ private EditTextPreference mCustomRoutes;
+ private CheckBoxPreference mUseDefaultRoute;
+ private EditTextPreference mCustomRoutesv6;
+ private CheckBoxPreference mUseDefaultRoutev6;
+ private CheckBoxPreference mRouteNoPull;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.vpn_routing);
+ mCustomRoutes = (EditTextPreference) findPreference("customRoutes");
+ mUseDefaultRoute = (CheckBoxPreference) findPreference("useDefaultRoute");
+ mCustomRoutesv6 = (EditTextPreference) findPreference("customRoutesv6");
+ mUseDefaultRoutev6 = (CheckBoxPreference) findPreference("useDefaultRoutev6");
+ mRouteNoPull = (CheckBoxPreference) findPreference("routenopull");
+
+ mCustomRoutes.setOnPreferenceChangeListener(this);
+ mCustomRoutesv6.setOnPreferenceChangeListener(this);
+
+ loadSettings();
+ }
+
+ @Override
+ protected void loadSettings() {
+
+ mUseDefaultRoute.setChecked(mProfile.mUseDefaultRoute);
+ mUseDefaultRoutev6.setChecked(mProfile.mUseDefaultRoutev6);
+
+ mCustomRoutes.setText(mProfile.mCustomRoutes);
+ mCustomRoutesv6.setText(mProfile.mCustomRoutesv6);
+
+ mRouteNoPull.setChecked(mProfile.mRoutenopull);
+
+ // Sets Summary
+ onPreferenceChange(mCustomRoutes, mCustomRoutes.getText());
+ onPreferenceChange(mCustomRoutesv6, mCustomRoutesv6.getText());
+ mRouteNoPull.setEnabled(mProfile.mUsePull);
+ }
+
+
+ @Override
+ protected void saveSettings() {
+ mProfile.mUseDefaultRoute = mUseDefaultRoute.isChecked();
+ mProfile.mUseDefaultRoutev6 = mUseDefaultRoutev6.isChecked();
+ mProfile.mCustomRoutes = mCustomRoutes.getText();
+ mProfile.mCustomRoutesv6 = mCustomRoutesv6.getText();
+ mProfile.mRoutenopull = mRouteNoPull.isChecked();
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference,
+ Object newValue) {
+ if( preference == mCustomRoutes || preference == mCustomRoutesv6 )
+ preference.setSummary((String)newValue);
+
+ saveSettings();
+ return true;
+ }
+
+
+} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/fragments/ShowConfigFragment.java b/src/de/blinkt/openvpn/fragments/ShowConfigFragment.java
new file mode 100644
index 00000000..3c76a383
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/ShowConfigFragment.java
@@ -0,0 +1,89 @@
+package de.blinkt.openvpn.fragments;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ProfileManager;
+
+
+public class ShowConfigFragment extends Fragment {
+ private String configtext;
+ public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID");
+ final VpnProfile vp = ProfileManager.get(profileUUID);
+ View v=inflater.inflate(R.layout.viewconfig, container,false);
+ final TextView cv = (TextView) v.findViewById(R.id.configview);
+
+ int check=vp.checkProfile(getActivity());
+ if(check!=R.string.no_error_found) {
+ cv.setText(check);
+ configtext = getString(check);
+ }
+ else {
+ // Run in own Thread since Keystore does not like to be queried from the main thread
+
+ cv.setText("Generating config...");
+ startGenConfig(vp, cv);
+ }
+ return v;
+ }
+
+ private void startGenConfig(final VpnProfile vp, final TextView cv) {
+
+ new Thread() {
+ public void run() {
+ final String cfg=vp.getConfigFile(getActivity(),false);
+ configtext= cfg;
+ getActivity().runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ cv.setText(cfg);
+ }
+ });
+
+
+ };
+ }.start();
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.configmenu, menu);
+ }
+
+ private void shareConfig() {
+ Intent shareIntent = new Intent(Intent.ACTION_SEND);
+ shareIntent.putExtra(Intent.EXTRA_TEXT, configtext);
+ shareIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.export_config_title));
+ shareIntent.setType("text/plain");
+ startActivity(Intent.createChooser(shareIntent, "Export Configfile"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == R.id.sendConfig) {
+ shareConfig();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/src/de/blinkt/openvpn/fragments/VPNProfileList.java b/src/de/blinkt/openvpn/fragments/VPNProfileList.java
new file mode 100644
index 00000000..7a8362d1
--- /dev/null
+++ b/src/de/blinkt/openvpn/fragments/VPNProfileList.java
@@ -0,0 +1,320 @@
+package de.blinkt.openvpn.fragments;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.TreeSet;
+
+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.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.Html.ImageGetter;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import de.blinkt.openvpn.ConfigConverter;
+import de.blinkt.openvpn.FileSelect;
+import de.blinkt.openvpn.LaunchVPN;
+import de.blinkt.openvpn.R;
+import de.blinkt.openvpn.VPNPreferences;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ProfileManager;
+
+public class VPNProfileList extends ListFragment {
+
+ public final static int RESULT_VPN_DELETED = Activity.RESULT_FIRST_USER;
+
+ 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 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) {
+ mEditProfile =(VpnProfile) getListAdapter().getItem(position);
+ editVPN(mEditProfile);
+
+ }
+ });
+
+ return v;
+ }
+ }
+
+
+
+
+
+
+
+
+ private ArrayAdapter<VpnProfile> mArrayadapter;
+
+ protected VpnProfile mEditProfile=null;
+
+
+
+ @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(android.R.drawable.ic_menu_add);
+ else if("ic_menu_archive".equals(source))
+ d = getActivity().getResources().getDrawable(R.drawable.ic_menu_archive);
+
+
+
+ if(d!=null) {
+ d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ return d;
+ }else{
+ return null;
+ }
+ }
+ }
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.vpn_profile_list, container,false);
+
+ 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));
+
+
+
+ return v;
+
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setListAdapter();
+ }
+
+ class VpnProfileNameComperator implements Comparator<VpnProfile> {
+
+ @Override
+ public int compare(VpnProfile lhs, VpnProfile rhs) {
+ return lhs.mName.compareTo(rhs.mName);
+ }
+
+ }
+
+ 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 VpnProfileNameComperator());
+ 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(android.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_archive)
+ .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) {
+ onAddProfileClicked();
+ return true;
+ } else if (itemId == MENU_IMPORT_PROFILE) {
+ startImportConfig();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ 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);
+ }
+
+
+
+
+
+ private void onAddProfileClicked() {
+ Context context = getActivity();
+ if (context != null) {
+ final EditText entry = new EditText(context);
+ entry.setSingleLine();
+
+ AlertDialog.Builder dialog = new AlertDialog.Builder(context);
+ dialog.setTitle(R.string.menu_add_profile);
+ dialog.setMessage(R.string.add_profile_name_prompt);
+ dialog.setView(entry);
+
+
+ dialog.setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String name = entry.getText().toString();
+ if (getPM().getProfileByName(name)==null) {
+ VpnProfile profile = new VpnProfile(name);
+ addProfile(profile);
+ } else {
+ Toast.makeText(getActivity(), R.string.duplicate_profile_name, Toast.LENGTH_LONG).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 ProfileManager getPM() {
+ return ProfileManager.getInstance(getActivity());
+ }
+
+
+ @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);
+ }
+
+ if(resultCode != Activity.RESULT_OK)
+ return;
+
+ if (requestCode == START_VPN_CONFIG) {
+ String configuredVPN = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
+
+ VpnProfile profile = ProfileManager.get(configuredVPN);
+ getPM().saveProfile(getActivity(), profile);
+ // Name could be modified, reset List adapter
+ setListAdapter();
+
+ } else if(requestCode== SELECT_PROFILE) {
+ String filedata = data.getStringExtra(FileSelect.RESULT_DATA);
+ Intent startImport = new Intent(getActivity(),ConfigConverter.class);
+ startImport.setAction(ConfigConverter.IMPORT_PROFILE);
+ Uri uri = new Uri.Builder().path(filedata).scheme("file").build();
+ startImport.setData(uri);
+ startActivityForResult(startImport, IMPORT_PROFILE);
+ } else if(requestCode == IMPORT_PROFILE) {
+ String profileUUID = data.getStringExtra(VpnProfile.EXTRA_PROFILEUUID);
+ mArrayadapter.add(ProfileManager.get(profileUUID));
+ }
+
+ }
+
+
+ private void editVPN(VpnProfile profile) {
+
+ Intent vprefintent = new Intent(getActivity(),VPNPreferences.class)
+ .putExtra(getActivity().getPackageName() + ".profileUUID", profile.getUUID().toString());
+
+ 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, profile.getUUID().toString());
+ intent.setAction(Intent.ACTION_MAIN);
+ startActivity(intent);
+
+ getActivity().finish();
+ }
+}