summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml16
-rw-r--r--README.txt4
-rw-r--r--res/layout/basic_settings.xml (renamed from res/layout/config.xml)0
-rw-r--r--res/layout/vpn_preference_layout.xml2
-rw-r--r--res/layout/vpn_preference_widget.xml8
-rw-r--r--res/values/arrays.xml9
-rw-r--r--res/values/strings.xml5
-rw-r--r--res/xml/main_about.xml5
-rw-r--r--res/xml/main_headers.xml14
-rw-r--r--res/xml/vpn_authentification.xml6
-rw-r--r--res/xml/vpn_headers.xml26
-rw-r--r--res/xml/vpn_overview.xml15
-rw-r--r--res/xml/vpn_profile_list.xml4
-rw-r--r--src/de/blinkt/openvpn/AboutActivity.java22
-rw-r--r--src/de/blinkt/openvpn/AboutFragment.java27
-rw-r--r--src/de/blinkt/openvpn/AboutPreference.java14
-rw-r--r--src/de/blinkt/openvpn/BasicSettings.java332
-rw-r--r--src/de/blinkt/openvpn/MainActivity.java13
-rw-r--r--src/de/blinkt/openvpn/OpenVPNClient.java3
-rw-r--r--src/de/blinkt/openvpn/ShowConfigFragment.java8
-rw-r--r--src/de/blinkt/openvpn/VPNConfigPreference.java54
-rw-r--r--src/de/blinkt/openvpn/VPNDatabase.java0
-rw-r--r--src/de/blinkt/openvpn/VPNPreferenceFragment.java0
-rw-r--r--src/de/blinkt/openvpn/VPNPreferences.java17
-rw-r--r--src/de/blinkt/openvpn/VPNProfileList.java235
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java106
26 files changed, 847 insertions, 98 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 24c8f164..332947dc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -24,27 +24,27 @@
<uses-sdk android:minSdkVersion="14" />
- <!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> -->
-
+ <!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> -->
<application
- android:debuggable="true"
+ android:debuggable="true"
android:icon="@drawable/icon"
android:label="@string/app" >
-
<activity android:name="com.lamerman.FileDialog" />
- <activity android:name=".AboutActivity" />
+ <activity android:name=".AboutFragment" />
<activity android:name=".VPNPreferences" />
<activity android:name=".LogWindow" />
- <activity
- android:name=".OpenVPNClient"
- android:configChanges="orientation|keyboardHidden" >
+ <activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity
+ android:name=".OpenVPNClient"
+ android:configChanges="orientation|keyboardHidden" >
+ </activity>
<service
android:name=".OpenVpnService"
diff --git a/README.txt b/README.txt
new file mode 100644
index 00000000..059d45e7
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,4 @@
+This is my first Android project, so some things my be done in a completly stupid way.
+
+
+I am for example not really sure if it was a good idea to use the Preferences Framework for the preferences \ No newline at end of file
diff --git a/res/layout/config.xml b/res/layout/basic_settings.xml
index cfe8c6e3..cfe8c6e3 100644
--- a/res/layout/config.xml
+++ b/res/layout/basic_settings.xml
diff --git a/res/layout/vpn_preference_layout.xml b/res/layout/vpn_preference_layout.xml
index 4d1f7e2e..15fc91ab 100644
--- a/res/layout/vpn_preference_layout.xml
+++ b/res/layout/vpn_preference_layout.xml
@@ -79,7 +79,7 @@
android:background="@android:drawable/divider_horizontal_dark" />
<ImageView
- android:id="@+id/vpn_edit_settings"
+ android:id="@+id/quickedit_settings"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
diff --git a/res/layout/vpn_preference_widget.xml b/res/layout/vpn_preference_widget.xml
deleted file mode 100644
index fef23003..00000000
--- a/res/layout/vpn_preference_widget.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<CheckBox
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+android:id/checkbox"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:focusable="false"
- android:clickable="false" /> \ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index eb2c1b1c..41d523e3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -8,6 +8,15 @@
<item>Static Keys</item>
</string-array>
+ <string-array name="vpn_entry_types">
+ <item>certs</item>
+ <item>pkcs12</item>
+ <item>keystore</item>
+ <item>userpw</item>
+ <item>statickeys</item>
+ </string-array>
+
+
<string-array name="tls_directions">
<item>0</item>
<item>1</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a9c1b1dc..79b7f8a7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -93,8 +93,9 @@
<string name="auth_pwquery">Password</string>
<string name="static_keys_info">For the static configuration the TLS Auth Keys will be used as static keys.</string>
<string name="configure_the_vpn">Configure the VPN</string>
-
-
+ <string name="menu_add_profile">Add Profile</string>
+ <string name="add_profile_name_prompt">Enter a name identifying the new Profile</string>
+ <string name="duplicate_profile_name">Duplicate Profile Name</string>
</resources>
diff --git a/res/xml/main_about.xml b/res/xml/main_about.xml
new file mode 100644
index 00000000..8e3e28dc
--- /dev/null
+++ b/res/xml/main_about.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+ <de.blinkt.openvpn.AboutPreference />
+
+</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/main_headers.xml b/res/xml/main_headers.xml
new file mode 100644
index 00000000..a0c4f432
--- /dev/null
+++ b/res/xml/main_headers.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <header
+ android:fragment="de.blinkt.openvpn.VPNProfileList"
+ android:summary="List of all VPN, confusing to be here :)"
+ android:title="All your precious VPNs" />
+ <header
+ android:fragment="de.blinkt.openvpn.AboutFragment"
+ android:summary="About Openvpn for Android"
+ android:title="About" />
+
+
+</preference-headers> \ No newline at end of file
diff --git a/res/xml/vpn_authentification.xml b/res/xml/vpn_authentification.xml
index 11ea3abe..949093d6 100644
--- a/res/xml/vpn_authentification.xml
+++ b/res/xml/vpn_authentification.xml
@@ -3,9 +3,9 @@
<CheckBoxPreference
android:key="remoteServerTLS"
- android:summary="Checks whether the server use a TLS Server Certificate"
+ android:summary="Checks whether the server uses a TLS Server Certificate"
android:title="Except TLS Server" />
- <de.blinkt.openvpn.VPNConfigPreference
- android:title="Whaaaaats UUUUuuuuup?" />
+
+ <CheckBoxPreference android:key="useTLSAuth"/>
</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/vpn_headers.xml b/res/xml/vpn_headers.xml
index 7d0ade3f..424b4411 100644
--- a/res/xml/vpn_headers.xml
+++ b/res/xml/vpn_headers.xml
@@ -1,23 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
- <header android:summary="Server, port and authentication method. Normally you should only settings specified here." >
- android:title="Basic Setting"
- <intent
- android:targetClass="de.blinkt.openvpn.OpenVPNClient"
- android:targetPackage="de.binkt.openvpn" />
- </header>
+ <header
+ android:fragment="de.blinkt.openvpn.BasicSettings"
+ android:summary="Server, port and authentication method. Normally you should only settings specified here."
+ android:title="Basic Settings" />
<!-- android:icon="@drawable/ic_settings_applications" -->
+
<header
android:fragment="de.blinkt.openvpn.VPNPreferences$IP_Settings"
android:summary="IP Address and Routing"
android:title="IP Settings" />
-
- <header
+ <header
android:fragment="de.blinkt.openvpn.VPNPreferences$Authentication"
android:summary="Authentication"
android:title="Authentication" />
-
<!-- android:icon="@drawable/ic_settings_display" -->
<header
@@ -33,14 +30,9 @@
android:name="someKey"
android:value="someHeaderValue" />
</header>
-
- <!-- android:icon="@drawable/ic_settings_display" -->
<header
- android:summary="Launches an Intent."
- android:title="Intent" >
- <intent
- android:action="android.intent.action.VIEW"
- android:data="http://www.android.com" />
- </header>
+ android:fragment="de.blinkt.openvpn.ShowConfigFragment"
+ android:summary="Shows the generated openvpn Configuration File"
+ android:title="Generated Config" />
</preference-headers> \ No newline at end of file
diff --git a/res/xml/vpn_overview.xml b/res/xml/vpn_overview.xml
deleted file mode 100644
index 053f2526..00000000
--- a/res/xml/vpn_overview.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/vpn_settings_activity_title" >
-
- <PreferenceScreen
- android:key="new_vpn"
- android:title="@string/new_vpn" />
-
- <PreferenceCategory
- android:fragment="de.blinkt.openvpn.VPNList$ListFragment"
- android:key="vpn_list"
- android:title="@string/vpn" >
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/res/xml/vpn_profile_list.xml b/res/xml/vpn_profile_list.xml
new file mode 100644
index 00000000..b1ce1a1a
--- /dev/null
+++ b/res/xml/vpn_profile_list.xml
@@ -0,0 +1,4 @@
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:key="profiles_list" /> \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/AboutActivity.java b/src/de/blinkt/openvpn/AboutActivity.java
deleted file mode 100644
index 0361d67c..00000000
--- a/src/de/blinkt/openvpn/AboutActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.blinkt.openvpn;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-public class AboutActivity extends Activity implements OnClickListener {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.about);
-
- //findViewById(R.layout.about).setOnClickListener(this);
- }
-
- @Override
- public void onClick(View v) {
- finish();
- }
-}
diff --git a/src/de/blinkt/openvpn/AboutFragment.java b/src/de/blinkt/openvpn/AboutFragment.java
new file mode 100644
index 00000000..a5b5695e
--- /dev/null
+++ b/src/de/blinkt/openvpn/AboutFragment.java
@@ -0,0 +1,27 @@
+package de.blinkt.openvpn;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+
+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);
+ return v;
+ }
+
+}
diff --git a/src/de/blinkt/openvpn/AboutPreference.java b/src/de/blinkt/openvpn/AboutPreference.java
new file mode 100644
index 00000000..ff6c611d
--- /dev/null
+++ b/src/de/blinkt/openvpn/AboutPreference.java
@@ -0,0 +1,14 @@
+package de.blinkt.openvpn;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+
+public class AboutPreference extends Preference {
+
+ public AboutPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.about);
+ }
+
+}
diff --git a/src/de/blinkt/openvpn/BasicSettings.java b/src/de/blinkt/openvpn/BasicSettings.java
new file mode 100644
index 00000000..271b8085
--- /dev/null
+++ b/src/de/blinkt/openvpn/BasicSettings.java
@@ -0,0 +1,332 @@
+/*
+ * 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;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Random;
+import java.util.Vector;
+
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.VpnService;
+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.security.KeyChainException;
+import android.util.Log;
+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.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+import com.lamerman.FileDialog;
+
+import de.blinkt.openvpn.R.id;
+
+public class BasicSettings extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback, OnCheckedChangeListener {
+ private static final String TAG = "OpenVpnClient";
+
+
+ private static final int START_OPENVPN = 0;
+ private static final int CHOOSE_FILE_OFFSET = 1000;
+ private static final int UPDATE_ALIAS = 20;
+
+ private static final String PREFS_NAME = "OVPN_SERVER";
+
+ private static final String OVPNCONFIGFILE = "android.conf";
+ private static final String OVPNCONFIGPKCS12 = "android.pkcs12";
+
+
+ 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 CheckBox mUseTlsAuth;
+
+
+ private CheckBox mShowAdvanced;
+
+
+ private FileSelectLayout mTlsFile;
+
+ private HashMap<Integer, FileSelectLayout> fileselects = new HashMap<Integer, FileSelectLayout>();
+
+
+ private Spinner mTLSDirection;
+
+
+ private EditText mUserName;
+
+
+ private EditText mPassword;
+
+
+ private View mView;
+
+
+ private VpnProfile mProfile;
+
+
+
+ private void addFileSelectLayout (FileSelectLayout fsl) {
+ int i = fileselects.size() + CHOOSE_FILE_OFFSET;
+ fileselects.put(i, fsl);
+ fsl.setActivity(getActivity(),i);
+ }
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ mView = inflater.inflate(R.layout.basic_settings,container,false);
+
+
+ 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);
+ mUseTlsAuth = (CheckBox) mView.findViewById(R.id.useTLSAuth);
+ mTLSDirection = (Spinner) mView.findViewById(R.id.tls_direction);
+
+ mShowAdvanced = (CheckBox) mView.findViewById(R.id.show_advanced);
+ mTlsFile = (FileSelectLayout) mView.findViewById(R.id.tlsAuth);
+ mUserName = (EditText) mView.findViewById(R.id.auth_username);
+ mPassword = (EditText) mView.findViewById(R.id.auth_password);
+
+
+ addFileSelectLayout(mCaCert);
+ addFileSelectLayout(mClientCert);
+ addFileSelectLayout(mClientKey);
+ addFileSelectLayout(mTlsFile);
+ addFileSelectLayout(mpkcs12);
+
+ loadPreferences();
+
+ mType.setOnItemSelectedListener(this);
+
+ mShowAdvanced.setOnCheckedChangeListener(this);
+ mUseTlsAuth.setOnCheckedChangeListener(this);
+
+
+ mView.findViewById(R.id.select_keystore_button).setOnClickListener(this);
+ mView.findViewById(R.id.about).setOnClickListener(this);
+ mView.findViewById(R.id.connect).setOnClickListener(this);
+
+ if (mHandler == null) {
+ mHandler = new Handler(this);
+ }
+ return mView;
+ }
+
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ if (parent == mType) {
+ changeType(position);
+ }
+ }
+
+
+
+ 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);
+
+ switch(type) {
+ case VpnProfile.TYPE_CERTIFICATES:
+ mView.findViewById(R.id.certs).setVisibility(View.VISIBLE);
+ break;
+ 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_KEYSTORE:
+ mView.findViewById(R.id.keystore).setVisibility(View.VISIBLE);
+ break;
+
+ case VpnProfile.TYPE_USERPASS:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
+ }
+
+
+ }
+
+ private void loadPreferences() {
+ mProfile = ((VPNPreferences)getActivity()).getVPNProfile();
+
+ 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);
+
+ mUseTlsAuth.setChecked(mProfile.mUseTLSAuth);
+ onCheckedChanged(mUseTlsAuth,mUseTlsAuth.isChecked());
+
+ mTlsFile.setData(mProfile.mTLSAuthFilename);
+ mTLSDirection.setSelection(mProfile.mTLSAuthDirection);
+ setAlias();
+
+ }
+
+ private void savePreferences() {
+ // We need an Editor object to make preference changes.
+ // All objects are from android.context.Context
+
+
+ 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.mUseTLSAuth =mUseTlsAuth.isChecked();
+ mProfile.mTLSAuthFilename= mTlsFile.getData();
+ mProfile.mTLSAuthDirection =mTLSDirection.getSelectedItemPosition();
+ // Commit the edits!
+
+ }
+
+
+ private void setAlias() {
+ if(mProfile.mAlias == null) {
+ mAliasName.setText(R.string.client_no_certificate);
+ } else {
+ mAliasName.setText(mProfile.mAlias);
+ }
+ }
+
+ public void showCertDialog () {
+ 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", "DSA"}, // List of acceptable key types. null for any
+ null, // issuer, null for any
+ "internal.example.com", // host name of server requesting the cert, null if unavailable
+ 443, // port of server requesting the cert, -1 if unavailable
+ null); // alias to preselect, null if unavailable
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mView.findViewById(R.id.select_keystore_button)) {
+ showCertDialog();
+ }
+ }
+
+
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ setAlias();
+ return true;
+ }
+
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ int visibility;
+ if(isChecked)
+ visibility =View.VISIBLE;
+ else
+ visibility =View.GONE;
+
+ if(buttonView==mShowAdvanced) {
+ mView.findViewById(R.id.advanced_options).setVisibility(visibility);
+ } else if (buttonView == mUseTlsAuth) {
+ mView.findViewById(R.id.tlsauth_options).setVisibility(visibility);
+ }
+ }
+}
diff --git a/src/de/blinkt/openvpn/MainActivity.java b/src/de/blinkt/openvpn/MainActivity.java
new file mode 100644
index 00000000..bc823745
--- /dev/null
+++ b/src/de/blinkt/openvpn/MainActivity.java
@@ -0,0 +1,13 @@
+package de.blinkt.openvpn;
+
+import java.util.List;
+
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceActivity.Header;
+
+public class MainActivity extends PreferenceActivity {
+ @Override
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.main_headers, target);
+ }
+}
diff --git a/src/de/blinkt/openvpn/OpenVPNClient.java b/src/de/blinkt/openvpn/OpenVPNClient.java
index f1a32b63..5af0ae8f 100644
--- a/src/de/blinkt/openvpn/OpenVPNClient.java
+++ b/src/de/blinkt/openvpn/OpenVPNClient.java
@@ -250,7 +250,7 @@ public class OpenVPNClient extends Activity implements View.OnClickListener, OnI
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.config);
+ setContentView(R.layout.basic_settings);
// Forces early JNI Load
OpenVPN.foo();
@@ -490,6 +490,7 @@ public class OpenVPNClient extends Activity implements View.OnClickListener, OnI
} else if (v == findViewById(R.id.about)) {
//Intent intent = new Intent(getBaseContext(),AboutActivity.class);
Intent intent = new Intent(getBaseContext(),VPNPreferences.class);
+ intent.putExtra("foo","der bar war hier!");
startActivity(intent);
} else if (v == findViewById(R.id.select_keystore_button)) {
showCertDialog();
diff --git a/src/de/blinkt/openvpn/ShowConfigFragment.java b/src/de/blinkt/openvpn/ShowConfigFragment.java
new file mode 100644
index 00000000..91471e84
--- /dev/null
+++ b/src/de/blinkt/openvpn/ShowConfigFragment.java
@@ -0,0 +1,8 @@
+package de.blinkt.openvpn;
+
+import android.app.Fragment;
+
+
+public class ShowConfigFragment extends Fragment {
+
+}
diff --git a/src/de/blinkt/openvpn/VPNConfigPreference.java b/src/de/blinkt/openvpn/VPNConfigPreference.java
index 3afcfccb..0387ebdb 100644
--- a/src/de/blinkt/openvpn/VPNConfigPreference.java
+++ b/src/de/blinkt/openvpn/VPNConfigPreference.java
@@ -1,15 +1,55 @@
package de.blinkt.openvpn;
-import android.content.Context;
-import android.preference.CheckBoxPreference;
+import android.os.Bundle;
import android.preference.Preference;
-import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
-public class VPNConfigPreference extends Preference {
+public class VPNConfigPreference extends Preference implements OnClickListener {
- public VPNConfigPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWidgetLayoutResource(R.layout.vpn_preference_layout);
+
+ private OnQuickSettingsClickListener mOnQuickSettingsListener;
+ private ImageView mQuickPrefButton;
+
+
+ public VPNConfigPreference(VPNProfileList vpnProfileList, Bundle args) {
+
+ super(vpnProfileList.getActivity());
+ setWidgetLayoutResource(R.layout.vpn_preference_layout);
+
+
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ mQuickPrefButton = (ImageView) view.findViewById(R.id.quickedit_settings);
+ mQuickPrefButton.setOnClickListener(this);
}
+ public interface OnQuickSettingsClickListener {
+ /**
+ * Called when a Preference has been clicked.
+ *
+ * @param preference The Preference that was clicked.
+ * @return True if the click was handled.
+ */
+ boolean onQuickSettingsClick(Preference preference);
+ }
+
+
+ public void setOnQuickSettingsClickListener(OnQuickSettingsClickListener onQuickSettingsListener) {
+ mOnQuickSettingsListener = onQuickSettingsListener;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mOnQuickSettingsListener != null) {
+ mOnQuickSettingsListener.onQuickSettingsClick(this);
+ }
+
+ }
+
+
}
diff --git a/src/de/blinkt/openvpn/VPNDatabase.java b/src/de/blinkt/openvpn/VPNDatabase.java
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/de/blinkt/openvpn/VPNDatabase.java
diff --git a/src/de/blinkt/openvpn/VPNPreferenceFragment.java b/src/de/blinkt/openvpn/VPNPreferenceFragment.java
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/de/blinkt/openvpn/VPNPreferenceFragment.java
diff --git a/src/de/blinkt/openvpn/VPNPreferences.java b/src/de/blinkt/openvpn/VPNPreferences.java
index 69485efd..6c68e444 100644
--- a/src/de/blinkt/openvpn/VPNPreferences.java
+++ b/src/de/blinkt/openvpn/VPNPreferences.java
@@ -2,7 +2,9 @@ package de.blinkt.openvpn;
import java.util.List;
+import android.content.Intent;
import android.os.Bundle;
+import android.os.Parcelable;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
@@ -16,6 +18,7 @@ import android.widget.Button;
public class VPNPreferences extends PreferenceActivity {
+ private VpnProfile mProfile;
public VPNPreferences() {
super();
}
@@ -23,6 +26,8 @@ public class VPNPreferences extends PreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mProfile = getIntent().getParcelableExtra("VpnProfile");
+
if (hasHeaders()) {
Button button = new Button(this);
button.setText("Some action");
@@ -47,12 +52,13 @@ public class VPNPreferences extends PreferenceActivity {
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");
@@ -69,8 +75,14 @@ public class VPNPreferences extends PreferenceActivity {
mDNS2.setOnPreferenceChangeListener(this);
mUsePull.setOnPreferenceChangeListener(this);
mOverrideDNS.setOnPreferenceChangeListener(this);
+
+
+ VpnProfile vp = ((VPNPreferences) getActivity()).getVPNProfile();
+
+
setDNSState();
+
}
@Override
@@ -134,5 +146,8 @@ public class VPNPreferences extends PreferenceActivity {
addPreferencesFromResource(R.xml.vpn_obscure);
}
}
+ public VpnProfile getVPNProfile() {
+ return mProfile;
+ }
}
diff --git a/src/de/blinkt/openvpn/VPNProfileList.java b/src/de/blinkt/openvpn/VPNProfileList.java
index fb7af280..74c857d3 100644
--- a/src/de/blinkt/openvpn/VPNProfileList.java
+++ b/src/de/blinkt/openvpn/VPNProfileList.java
@@ -1,22 +1,233 @@
package de.blinkt.openvpn;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.StreamCorruptedException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import de.blinkt.openvpn.VPNConfigPreference.OnQuickSettingsClickListener;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.EditText;
+import android.widget.Toast;
+
+public class VPNProfileList extends PreferenceFragment implements OnPreferenceClickListener, OnQuickSettingsClickListener {
+ private static final String PREFS_NAME = "VPNList";
+
+ private static final int MENU_ADD_PROFILE = Menu.FIRST;
+
+
+ private HashMap<String,VpnProfile> profiles;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.vpn_profile_list);
+ setHasOptionsMenu(true);
+
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ refreshList();
+
+
+ }
+
+ @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')
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
+ | 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 {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ 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 (getProfileByName(name)==null) {
+ VpnProfile profile = new VpnProfile(name);
+ addProfile(profile);
+ refreshList();
+ } else {
+ Toast.makeText(getActivity(), R.string.duplicate_profile_name, Toast.LENGTH_LONG).show();
+ }
+ }
+
+
+ });
+ dialog.setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ dialog.create().show();
+ }
+
+ }
+
+ public VpnProfile getProfileByName(String name) {
+ for (VpnProfile vpnp : profiles.values()) {
+ if(vpnp.getName().equals(name)) {
+ return vpnp;
+ }
+ }
+ return null;
+ }
+
+ private void addProfile(VpnProfile profile) {
+ profiles.put(profile.getUUID().toString(),profile);
+ Editor editor = getActivity().getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE).edit();
+ editor.putStringSet("vpnlist", profiles.keySet());
+ editor.commit();
+ saveProfile(profile);
+
+ }
+
+
+ private void saveProfile(VpnProfile profile) {
+ ObjectOutputStream vpnfile;
+ try {
+ vpnfile = new ObjectOutputStream(getActivity().openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE));
+
+ vpnfile.writeObject(profile);
+ vpnfile.flush();
+ vpnfile.close();
+ } catch (FileNotFoundException e) {
+
+ e.printStackTrace();
+ } catch (IOException e) {
+
+ e.printStackTrace();
+ }
+ }
+
+ private void loadVPNList() {
+ profiles = new HashMap<String, VpnProfile>();
+ SharedPreferences settings =getActivity().getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE);
+ Set<String> vlist = settings.getStringSet("vpnlist", null);
+ if(vlist==null){
+ vlist = new HashSet<String>();
+ }
+
+ for (String vpnentry : vlist) {
+ try {
+ ObjectInputStream vpnfile = new ObjectInputStream(getActivity().openFileInput(vpnentry + ".vp"));
+ VpnProfile vp = ((VpnProfile) vpnfile.readObject());
+
+ profiles.put(vp.getUUID().toString(), vp);
+
+ } catch (StreamCorruptedException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ public void refreshList() {
+ PreferenceScreen plist = getPreferenceScreen();
+ if (plist != null) {
+ plist.removeAll();
+ loadVPNList();
+
+ for (VpnProfile vpnprofile: profiles.values()) {
+ Bundle args = new Bundle();
+ //TODO
+
+ String profileuuid = vpnprofile.getUUID().toString();
+
+
+ args.putParcelable("Profile", vpnprofile);
+ //args.putString("name", vpnentry);
+ VPNConfigPreference vpref = new VPNConfigPreference(this, args);
+ vpref.setKey(profileuuid);
+ vpref.setTitle(vpnprofile.getName());
+ vpref.setPersistent(false);
+ // vpref.setSelectable(true);
+ vpref.setOnPreferenceClickListener(this);
+ vpref.setOnQuickSettingsClickListener(this);
+ plist.addPreference(vpref);
+ }
+
+ }
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ String key= preference.getKey();
+
+ return true;
-import android.app.ProfileManager;
+ }
-public class VPNProfileList extends PreferenceActivity {
- private ProfileManager mProfileManager;
+ @Override
+ public boolean onQuickSettingsClick(Preference preference) {
+ String key = preference.getKey();
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ VpnProfile vprofile = profiles.get(key);
- if (getPreferenceManager() != null) {
- addPreferencesFromResource(R.xml.profiles_settings);
- mProfileManager = (ProfileManager) getActivity().getSystemService(PROFILE_SERVICE);
+ Intent vprefintent = new Intent(getActivity(),VPNPreferences.class)
+ .putExtra("VpnProfile", (Parcelable)vprofile);
- }
- }
+ startActivity(vprefintent);
+ return true;
+ }
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 8d5fbe32..0eddabaa 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -1,10 +1,114 @@
package de.blinkt.openvpn;
-public class VpnProfile {
+import java.io.Serializable;
+import java.util.UUID;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class VpnProfile implements Parcelable, Serializable{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7085688938959334563L;
static final int TYPE_CERTIFICATES=0;
static final int TYPE_PKCS12=1;
static final int TYPE_KEYSTORE=2;
public static final int TYPE_USERPASS = 3;
public static final int TYPE_STATICKEYS = 4;
+
+ // Keep in order of parceling
+ // Public attributes, since I got mad with getter/setter
+ // set members to default values
+ private UUID mUuid;
+ public int mAuthenticationType = TYPE_KEYSTORE ;
+ public String mName;
+ public String mAlias;
+ public String mClientCertFilename;
+ public int mTLSAuthDirection=2;
+ public String mTLSAuthFilename;
+ public String mClientKeyFilename;
+ public String mCaFilename;
+ public boolean mUseLzo=true;
+ public String mServerPort= "1194" ;
+ public boolean mUseUdp = true;
+ public String mPKCS12Filename;
+ public String mPKCS12Password;
+ public boolean mUseTLSAuth = false;
+ public String mServerName = "openvpn.blinkt.de" ;
+
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mAuthenticationType);
+ out.writeLong(mUuid.getMostSignificantBits());
+ out.writeLong(mUuid.getLeastSignificantBits());
+ out.writeString(mName);
+ out.writeString(mAlias);
+ out.writeString(mClientCertFilename);
+ out.writeInt(mTLSAuthDirection);
+ out.writeString(mTLSAuthFilename);
+ out.writeString(mClientKeyFilename);
+ out.writeString(mCaFilename);
+ out.writeValue(mUseLzo);
+ out.writeString(mServerPort);
+ out.writeValue(mUseUdp);
+ out.writeString(mPKCS12Filename);
+ out.writeString(mPKCS12Password);
+ out.writeValue(mUseTLSAuth);
+ out.writeString(mServerName);
+ }
+
+ private VpnProfile(Parcel in) {
+ mAuthenticationType = in.readInt();
+ mUuid = new UUID(in.readLong(), in.readLong());
+ mName = in.readString();
+ mAlias = in.readString();
+ mClientCertFilename = in.readString();
+ mTLSAuthDirection = in.readInt();
+ mTLSAuthFilename = in.readString();
+ mClientKeyFilename = in.readString();
+ mCaFilename = in.readString();
+ mUseLzo = (Boolean) in.readValue(null);
+ mServerPort = in.readString();
+ mUseUdp = (Boolean) in.readValue(null);
+ mPKCS12Filename = in.readString();
+ mPKCS12Password = in.readString();
+ mUseTLSAuth = (Boolean) in.readValue(null);
+ mServerName = in.readString();
+ }
+
+ public static final Parcelable.Creator<VpnProfile> CREATOR
+ = new Parcelable.Creator<VpnProfile>() {
+ public VpnProfile createFromParcel(Parcel in) {
+ return new VpnProfile(in);
+ }
+
+ public VpnProfile[] newArray(int size) {
+ return new VpnProfile[size];
+ }
+ };
+
+ public VpnProfile(String name) {
+ mUuid = UUID.randomUUID();
+ mName = name;
+ }
+
+ public UUID getUUID() {
+ return mUuid;
+
+ }
+
+ public String getName() {
+ // TODO Auto-generated method stub
+ return mName;
+ }
+
+
+
+
}