diff options
Diffstat (limited to 'main/src/main/java/de')
9 files changed, 521 insertions, 100 deletions
diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java index 6f21a847..aff2a362 100644 --- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -47,6 +47,7 @@ import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import de.blinkt.openvpn.core.Connection; import de.blinkt.openvpn.core.NativeUtils; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.VPNLaunchHelper; @@ -67,7 +68,7 @@ public class VpnProfile implements Serializable { private static final long serialVersionUID = 7085688938959334563L; public static final int MAXLOGLEVEL = 4; - public static final int CURRENT_PROFILE_VERSION = 2; + public static final int CURRENT_PROFILE_VERSION = 4; public static final int DEFAULT_MSSFIX_SIZE = 1450; public static String DEFAULT_DNS1 = "8.8.8.8"; public static String DEFAULT_DNS2 = "8.8.4.4"; @@ -102,12 +103,10 @@ public class VpnProfile implements Serializable { 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 String mDNS1 = DEFAULT_DNS1; public String mDNS2 = DEFAULT_DNS2; public String mIPv4Address; @@ -148,6 +147,13 @@ public class VpnProfile implements Serializable { public String mExcludedRoutes; public String mExcludedRoutesv6; public int mMssFix =0; // -1 is default, + public Connection[] mConnections; + public boolean mRemoteRandom=false; + + /* Options no long used in new profiles */ + public String mServerName = "openvpn.blinkt.de"; + public String mServerPort = "1194"; + public boolean mUseUdp = true; @@ -202,7 +208,25 @@ public class VpnProfile implements Serializable { mAllowLocalLAN = Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT; } + + if (mProfileVersion < 4) + moveOptionsToConnection(); + mProfileVersion= CURRENT_PROFILE_VERSION; + + } + + private void moveOptionsToConnection() { + mConnections = new Connection[1]; + Connection conn = new Connection(); + + conn.mServerName = mServerName; + conn.mServerPort = mServerPort; + conn.mUseUdp = mUseUdp; + conn.mCustomConfiguration = ""; + + mConnections[0] = conn; + } public String getConfigFile(Context context, boolean configForOvpn3) { @@ -263,15 +287,19 @@ public class VpnProfile implements Serializable { // We cannot use anything else than tun cfg += "dev tun\n"; - // Server Address - cfg += "remote "; - cfg += mServerName; - cfg += " "; - cfg += mServerPort; - if (mUseUdp) - cfg += " udp\n"; - else - cfg += " tcp-client\n"; + if (mConnections.length==1) { + cfg += mConnections[0].getConnectionBlock(); + } else { + if (mRemoteRandom) + cfg+="remote-random\n"; + for (Connection conn : mConnections) { + if (conn.mEnabled) { + cfg += "<connection>\n"; + cfg += conn.getConnectionBlock(); + cfg += "</connection>\n"; + } + } + } switch (mAuthenticationType) { diff --git a/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java b/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java index 1f022545..1641a51b 100644 --- a/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java +++ b/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java @@ -25,6 +25,7 @@ import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.fragments.Settings_Authentication; import de.blinkt.openvpn.fragments.Settings_Basic; import de.blinkt.openvpn.fragments.Settings_Behaviour; +import de.blinkt.openvpn.fragments.Settings_Connections; import de.blinkt.openvpn.fragments.Settings_IP; import de.blinkt.openvpn.fragments.Settings_Obscure; import de.blinkt.openvpn.fragments.Settings_Routing; @@ -37,7 +38,7 @@ public class VPNPreferences extends PreferenceActivity { static final Class validFragments[] = new Class[] { Settings_Authentication.class, Settings_Basic.class, Settings_IP.class, Settings_Obscure.class, Settings_Routing.class, ShowConfigFragment.class, - Settings_Behaviour.class + Settings_Behaviour.class, Settings_Connections.class }; private String mProfileUUID; diff --git a/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java index 9e99ba55..3015b6fe 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -5,9 +5,15 @@ package de.blinkt.openvpn.core; +import android.text.TextUtils; +import android.util.Pair; + import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; +import java.io.StringReader; import java.util.Collections; import java.util.HashMap; import java.util.Locale; @@ -28,9 +34,6 @@ public class ConfigParser { private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>(); private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>(); - - private boolean extraRemotesAsCustom=false; - public void parseConfig(Reader reader) throws IOException, ConfigParseError { @@ -53,7 +56,7 @@ public class ConfigParser { meta.put(metaarg.get(0),metaarg); continue; } - Vector<String> args = parseline(line); + Vector<String> args = parseline(line); if(args.size() ==0) continue; @@ -98,7 +101,7 @@ public class ConfigParser { break; else { inlinefile+=line; - inlinefile+= "\n"; + inlinefile+= "\n"; } } while(true); @@ -132,7 +135,7 @@ public class ConfigParser { // adapted openvpn's parse function to java private Vector<String> parseline(String line) throws ConfigParseError { - Vector<String> parameters = new Vector<String>(); + Vector<String> parameters = new Vector<String>(); if (line.length()==0) return parameters; @@ -145,12 +148,12 @@ public class ConfigParser { int pos=0; String currentarg=""; - do { + do { // Emulate the c parsing ... char in; if(pos < line.length()) in = line.charAt(pos); - else + else in = '\0'; if (!backslash && in == '\\' && state != linestate.readin_single_quote) @@ -228,10 +231,7 @@ public class ConfigParser { } - final String[] unsupportedOptions = { "config", - "connection", - "proto-force", - "remote-random", + final String[] unsupportedOptions = { "config", "tls-server" }; @@ -299,7 +299,7 @@ public class ConfigParser { "remote", "float", "port", -// "connect-retry", + "connect-retry", "connect-timeout", "connect-retry-max", "link-mtu", @@ -325,7 +325,7 @@ public class ConfigParser { // This method is far too long @SuppressWarnings("ConstantConditions") - public VpnProfile convertProfile() throws ConfigParseError{ + public VpnProfile convertProfile() throws ConfigParseError, IOException { boolean noauthtypeset=true; VpnProfile np = new VpnProfile(CONVERTED_PROFILE); // Pull, client, tls-client @@ -338,7 +338,7 @@ public class ConfigParser { } Vector<String> secret = getOption("secret", 1, 2); - if(secret!=null) + if(secret!=null) { np.mAuthenticationType=VpnProfile.TYPE_STATICKEYS; noauthtypeset=false; @@ -362,7 +362,7 @@ public class ConfigParser { if (route.size() >= 4) gateway = route.get(3); - String net = route.get(1); + String net = route.get(1); try { CIDRIP cidr = new CIDRIP(net, netmask); if (gateway.equals("net_gateway")) @@ -398,7 +398,7 @@ public class ConfigParser { Vector<Vector<String>> tlsauthoptions = getAllOption("tls-auth", 1, 2); if(tlsauthoptions!=null) { for(Vector<String> tlsauth:tlsauthoptions) { - if(tlsauth!=null) + if(tlsauth!=null) { if(!tlsauth.get(1).equals("[inline]")) { np.mTLSAuthFilename=tlsauth.get(1); @@ -458,36 +458,6 @@ public class ConfigParser { throw new ConfigParseError("Invalid mode for --mode specified, need p2p"); } - Vector<String> port = getOption("port", 1,1); - if(port!=null){ - np.mServerPort = port.get(1); - } - - Vector<String> rport = getOption("rport", 1,1); - if(rport!=null){ - np.mServerPort = rport.get(1); - } - - Vector<String> proto = getOption("proto", 1,1); - if(proto!=null){ - np.mUseUdp=isUdpProto(proto.get(1)); - } - - // Parse remote config - Vector<Vector<String>> remotes = getAllOption("remote",1,3); - - if(remotes!=null && remotes.size()>=1 ) { - Vector<String> remote = remotes.get(0); - switch (remote.size()) { - case 4: - np.mUseUdp=isUdpProto(remote.get(3)); - case 3: - np.mServerPort = remote.get(2); - case 2: - np.mServerName = remote.get(1); - } - } - Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-option", 2, 2); @@ -581,18 +551,18 @@ public class ConfigParser { if(verifyx509name!=null){ np.mRemoteCN = verifyx509name.get(1); np.mCheckRemoteCN=true; - if(verifyx509name.size()>2) { + if(verifyx509name.size()>2) { if (verifyx509name.get(2).equals("name")) np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN; else if (verifyx509name.get(2).equals("name-prefix")) np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX; - else + else throw new ConfigParseError("Unknown parameter to x509-verify-name: " + verifyx509name.get(2) ); } else { np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN; } - } + } Vector<String> verb = getOption("verb",1,1); @@ -615,7 +585,7 @@ public class ConfigParser { if(connectretrymax!=null) np.mConnectRetryMax =connectretrymax.get(1); - Vector<Vector<String>> remotetls = getAllOption("remote-cert-tls", 1, 1); + Vector<Vector<String>> remotetls = getAllOption("remote-cert-tls", 1, 1); if(remotetls!=null) if(remotetls.get(0).get(1).equals("server")) np.mExpectTLSCert=true; @@ -639,7 +609,49 @@ public class ConfigParser { } } - // Parse OpenVPN Access Server extra + Pair<Connection, Connection[]> conns = parseConnectionOptions(null); + np.mConnections =conns.second; + + Vector<Vector<String>> connectionBlocks = getAllOption("connection", 1, 1); + + if (np.mConnections.length > 0 && connectionBlocks !=null ) { + throw new ConfigParseError("Using a <connection> block and --remote is not allowed."); + } + + if (connectionBlocks!=null) { + np.mConnections = new Connection[connectionBlocks.size()]; + + int connIndex = 0; + for (Vector<String> conn : connectionBlocks) { + Pair<Connection, Connection[]> connectionBlockConnection = + parseConnection(conn.get(1), conns.first); + + if (connectionBlockConnection.second.length != 1) + throw new ConfigParseError("A <connection> block must have exactly one remote"); + np.mConnections[connIndex] = connectionBlockConnection.second[0]; + connIndex++; + } + } + if(getOption("remote-random", 0, 0) != null) + np.mRemoteRandom=true; + + Vector<String> protoforce = getOption("proto-force", 1, 1); + if(protoforce!=null) { + boolean disableUDP; + String protoToDisable = protoforce.get(1); + if (protoToDisable.equals("udp")) + disableUDP=true; + else if (protoToDisable.equals("tcp")) + disableUDP=false; + else + throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable)); + + for (Connection conn:np.mConnections) + if(conn.mUseUdp==disableUDP) + conn.mEnabled=false; + } + + // Parse OpenVPN Access Server extra Vector<String> friendlyname = meta.get("FRIENDLY_NAME"); if(friendlyname !=null && friendlyname.size() > 1) np.mName=friendlyname.get(1); @@ -649,20 +661,95 @@ public class ConfigParser { if(ocusername !=null && ocusername.size() > 1) np.mUsername=ocusername.get(1); - // Check the other options - if(remotes !=null && remotes.size()>1 && extraRemotesAsCustom) { - // first is already added - remotes.remove(0); - np.mCustomConfigOptions += getOptionStrings(remotes); - np.mUseCustomConfig=true; - - } - checkIgnoreAndInvalidOptions(np); + checkIgnoreAndInvalidOptions(np); fixup(np); return np; } + private Pair<Connection, Connection[]> parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError { + // Parse a connection Block as a new configuration file + + + ConfigParser connectionParser = new ConfigParser(); + StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length())); + connectionParser.parseConfig(reader); + + Pair<Connection, Connection[]> conn = connectionParser.parseConnectionOptions(defaultValues); + + return conn; + } + + private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault) throws ConfigParseError { + Connection conn; + if (connDefault!=null) + try { + conn = connDefault.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + else + conn = new Connection(); + + Vector<String> port = getOption("port", 1,1); + if(port!=null){ + conn.mServerPort = port.get(1); + } + + Vector<String> rport = getOption("rport", 1,1); + if(rport!=null){ + conn.mServerPort = rport.get(1); + } + + Vector<String> proto = getOption("proto", 1,1); + if(proto!=null){ + conn.mUseUdp=isUdpProto(proto.get(1)); + } + + + // Parse remote config + Vector<Vector<String>> remotes = getAllOption("remote",1,3); + + + // Assume that we need custom options if connectionDefault are set + if(connDefault!=null) { + for (Vector<Vector<String>> option : options.values()) { + + conn.mCustomConfiguration += getOptionStrings(option); + + } + if (!TextUtils.isEmpty(conn.mCustomConfiguration)) + conn.mUseCustomConfig = true; + } + // Make remotes empty to simplify code + if (remotes==null) + remotes = new Vector<Vector<String>>(); + + Connection[] connections = new Connection[remotes.size()]; + + + int i=0; + for (Vector<String> remote: remotes) { + try { + connections[i] = conn.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + switch (remote.size()) { + case 4: + connections[i].mUseUdp=isUdpProto(remote.get(3)); + case 3: + connections[i].mServerPort = remote.get(2); + case 2: + connections[i].mServerName = remote.get(1); + } + i++; + } + return Pair.create(conn, connections); + + } + private void checkRedirectParameters(VpnProfile np, Vector<Vector<String>> defgw) { for (Vector<String> redirect: defgw) for (int i=1;i<redirect.size();i++){ @@ -673,20 +760,16 @@ public class ConfigParser { } } - public void useExtraRemotesAsCustom(boolean b) { - this.extraRemotesAsCustom = b; - } - private boolean isUdpProto(String proto) throws ConfigParseError { boolean isudp; if(proto.equals("udp") || proto.equals("udp6")) isudp=true; else if (proto.equals("tcp-client") || - proto.equals("tcp") || + proto.equals("tcp") || proto.equals("tcp6") || proto.endsWith("tcp6-client")) isudp =false; - else + else throw new ConfigParseError("Unsupported option to --proto " + proto); return isudp; } diff --git a/main/src/main/java/de/blinkt/openvpn/core/Connection.java b/main/src/main/java/de/blinkt/openvpn/core/Connection.java new file mode 100644 index 00000000..88cde137 --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/core/Connection.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.core; + +import android.text.TextUtils; + +import java.io.Serializable; + +public class Connection implements Serializable, Cloneable { + public String mServerName = "openvpn.blinkt.de"; + public String mServerPort = "1194"; + public boolean mUseUdp = true; + public String mCustomConfiguration=""; + public boolean mUseCustomConfig=false; + public boolean mEnabled=true; + + + public String getConnectionBlock() { + String cfg=""; + + // Server Address + cfg += "remote "; + cfg += mServerName; + cfg += " "; + cfg += mServerPort; + if (mUseUdp) + cfg += " udp\n"; + else + cfg += " tcp-client\n"; + + if (!TextUtils.isEmpty(mCustomConfiguration) && mUseCustomConfig) { + cfg += mCustomConfiguration; + cfg += "\n"; + } + return cfg; + } + + @Override + public Connection clone() throws CloneNotSupportedException { + return (Connection) super.clone(); + } +} diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/ConnectionsAdapter.java b/main/src/main/java/de/blinkt/openvpn/fragments/ConnectionsAdapter.java new file mode 100644 index 00000000..3d20db73 --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/fragments/ConnectionsAdapter.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.fragments; + +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RadioGroup; +import android.widget.Switch; +import android.widget.TextView; + +import java.util.Arrays; + +import de.blinkt.openvpn.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.Connection; + +/** + * Created by arne on 30.10.14. + */ +public class ConnectionsAdapter extends BaseAdapter { + private final Context mContext; + private final VpnProfile mProfile; + private final Settings_Connections mConnectionFragment; + private Connection[] mConnections; + + public ConnectionsAdapter(Context c, Settings_Connections connections_fragments, VpnProfile vpnProfile) + { + mContext = c; + mConnections = vpnProfile.mConnections; + mProfile = vpnProfile; + mConnectionFragment = connections_fragments; + } + + @Override + public int getCount() { + return mConnections.length; + } + + @Override + public Object getItem(int position) { + return position; + } + + @Override + public long getItemId(int position) { + return 0; + } + + // create a new ImageView for each item referenced by the Adapter + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View card; + if (convertView==null) { + LayoutInflater li = LayoutInflater.from(mContext); + card = li.inflate(R.layout.server_card, parent, false); + } else { + card = convertView; + } + final Connection connection = mConnections[position]; + ((TextView)card.findViewById(R.id.portnumber)). + setText(connection.mServerPort); + + EditText serverNameView = (EditText) card.findViewById(R.id.servername); + EditText portNumberView = (EditText) card.findViewById(R.id.portnumber); + + serverNameView.setText(connection.mServerName); + portNumberView.setText(connection.mServerPort); + + Switch remoteSwitch = (Switch) card.findViewById (R.id.remoteSwitch); + remoteSwitch.setChecked(connection.mEnabled); + remoteSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + connection.mEnabled = isChecked; + displayWarningifNoneEnabled(); + } + }); + + + serverNameView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + connection.mServerName = s.toString(); + } + }); + + portNumberView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + connection.mServerPort = s.toString(); + } + }); + + CheckBox customOptionCB = (CheckBox) card.findViewById(R.id.use_customoptions); + final EditText editText = (EditText) card.findViewById(R.id.customoptions); + RadioGroup protoGroup = (RadioGroup) card.findViewById(R.id.udptcpradiogroup); + protoGroup.check(connection.mUseUdp ? R.id.udp_proto : R.id.tcp_proto); + protoGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + if (checkedId == R.id.udp_proto) + connection.mUseUdp=true; + else if (checkedId == R.id.tcp_proto) + connection.mUseUdp=false; + } + }); + + final View customOptionsLayout = card.findViewById(R.id.custom_options_layout); + + customOptionsLayout.setVisibility(connection.mUseCustomConfig ? View.VISIBLE : View.GONE); + editText.setText(connection.mCustomConfiguration); + + customOptionCB.setChecked(connection.mUseCustomConfig); + customOptionCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) + { + connection.mUseCustomConfig = isChecked; + customOptionsLayout.setVisibility(connection.mUseCustomConfig ? View.VISIBLE : View.GONE); + } + }); + displayWarningifNoneEnabled(); + return card; + } + + private void displayWarningifNoneEnabled() { + int showWarning = View.VISIBLE; + for(Connection conn:mConnections) { + if(conn.mEnabled) + showWarning= View.GONE; + } + mConnectionFragment.setWarningVisible(showWarning); + } + + public void addRemote() { + mConnections = Arrays.copyOf(mConnections, mConnections.length+1); + mConnections[mConnections.length-1] = new Connection(); + + notifyDataSetInvalidated(); + } + + public void saveProfile() { + mProfile.mConnections= mConnections; + } +} diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java index 52e8d784..1fda0a9c 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -30,7 +30,6 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; -import android.widget.ToggleButton; import java.security.cert.X509Certificate; @@ -45,15 +44,12 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On 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 TextView mAliasCertificate; private CheckBox mUseLzo; - private ToggleButton mTcpUdp; private Spinner mType; private FileSelectLayout mpkcs12; private TextView mPKCS12Password; @@ -129,14 +125,11 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On 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); @@ -262,9 +255,6 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On mCaCert.setData(mProfile.mCaFilename, getActivity()); mUseLzo.setChecked(mProfile.mUseLzo); - mServerPort.setText(mProfile.mServerPort); - mServerAddress.setText(mProfile.mServerName); - mTcpUdp.setChecked(mProfile.mUseUdp); mType.setSelection(mProfile.mAuthenticationType); mpkcs12.setData(mProfile.mPKCS12Filename, getActivity()); mPKCS12Password.setText(mProfile.mPKCS12Password); @@ -284,10 +274,6 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On 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(); diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java new file mode 100644 index 00000000..435bdb26 --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.fragments; + +import android.app.Fragment; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +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.AdapterView; +import android.widget.CheckBox; +import android.widget.GridView; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import org.w3c.dom.Text; + +import de.blinkt.openvpn.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ProfileManager; + +public class Settings_Connections extends Fragment implements View.OnClickListener { + private VpnProfile mProfile; + private ConnectionsAdapter mConnectionsAdapter; + private TextView mWarning; + private CheckBox mUseRandomRemote; + + @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())); + + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + inflater.inflate(R.menu.connections, menu); + super.onCreateOptionsMenu(menu, inflater); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.connections, container, false); + + GridView gridview = (GridView) v.findViewById(R.id.gridview); + + gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView<?> parent, View v, int position, long id) { + Toast.makeText(getActivity(), "" + position, Toast.LENGTH_SHORT).show(); + } + }); + + mConnectionsAdapter = new ConnectionsAdapter(getActivity(), this, mProfile); + gridview.setAdapter(mConnectionsAdapter); + + ImageButton fab_button = (ImageButton) v.findViewById(R.id.add_new_remote); + if(fab_button!=null) + fab_button.setOnClickListener(this); + + mUseRandomRemote = (CheckBox) v.findViewById(R.id.remote_random); + mUseRandomRemote.setChecked(mProfile.mRemoteRandom); + + mWarning = (TextView) v.findViewById(R.id.noserver_active_warning); + return v; + } + + + + @Override + public void onClick(View v) { + if (v.getId() == R.id.add_new_remote) { + mConnectionsAdapter.addRemote(); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId()==R.id.add_new_remote) + mConnectionsAdapter.addRemote(); + return super.onOptionsItemSelected(item); + } + + @Override + public void onPause() { + super.onPause(); + mConnectionsAdapter.saveProfile(); + mProfile.mRemoteRandom = mUseRandomRemote.isChecked(); + } + + public void setWarningVisible(int showWarning) { + mWarning.setVisibility(showWarning); + } +} diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Utils.java b/main/src/main/java/de/blinkt/openvpn/fragments/Utils.java index 2408956c..8676ccaf 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/Utils.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Utils.java @@ -109,7 +109,6 @@ public class Utils { // DocumentsContract.EXTRA_SHOW_ADVANCED is hidden i.putExtra("android.content.extra.SHOW_ADVANCED", true); - /* Samsung has decided to do something strange, on stock Android GET_CONTENT opens the document UI */ /* fist try with documentsui */ i.setPackage("com.android.documentsui"); diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java b/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java index e4911a41..d13d1ca6 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/VPNProfileList.java @@ -135,12 +135,8 @@ public class VPNProfileList extends ListFragment { 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; |