Merge branch 'android-updates'

Adds a copy function for VPN profiles and an option to set custom DNS
servers.
This commit is contained in:
Tobias Brunner 2019-03-14 10:56:07 +01:00
commit b4a23e3cea
21 changed files with 300 additions and 26 deletions

View File

@ -2,14 +2,13 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "org.strongswan.android"
minSdkVersion 15
targetSdkVersion 26
versionCode 62
versionName "2.0.2"
versionCode 63
versionName "2.1.0"
}
sourceSets.main {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2012-2019 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
@ -39,7 +39,7 @@ public class VpnProfile implements Cloneable
private String mName, mGateway, mUsername, mPassword, mCertificate, mUserCertificate;
private String mRemoteId, mLocalId, mExcludedSubnets, mIncludedSubnets, mSelectedApps;
private String mIkeProposal, mEspProposal;
private String mIkeProposal, mEspProposal, mDnsServers;
private Integer mMTU, mPort, mSplitTunneling, mNATKeepAlive, mFlags;
private SelectedAppsHandling mSelectedAppsHandling = SelectedAppsHandling.SELECTED_APPS_DISABLE;
private VpnType mVpnType;
@ -140,6 +140,16 @@ public class VpnProfile implements Cloneable
this.mEspProposal = proposal;
}
public String getDnsServers()
{
return mDnsServers;
}
public void setDnsServers(String dns)
{
this.mDnsServers = dns;
}
public String getUsername()
{
return mUsername;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2012-2019 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
@ -55,6 +55,7 @@ public class VpnProfileDataSource
public static final String KEY_FLAGS = "flags";
public static final String KEY_IKE_PROPOSAL = "ike_proposal";
public static final String KEY_ESP_PROPOSAL = "esp_proposal";
public static final String KEY_DNS_SERVERS = "dns_servers";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDatabase;
@ -63,7 +64,7 @@ public class VpnProfileDataSource
private static final String DATABASE_NAME = "strongswan.db";
private static final String TABLE_VPNPROFILE = "vpnprofile";
private static final int DATABASE_VERSION = 16;
private static final int DATABASE_VERSION = 17;
public static final DbColumn[] COLUMNS = new DbColumn[] {
new DbColumn(KEY_ID, "INTEGER PRIMARY KEY AUTOINCREMENT", 1),
@ -88,6 +89,7 @@ public class VpnProfileDataSource
new DbColumn(KEY_FLAGS, "INTEGER", 14),
new DbColumn(KEY_IKE_PROPOSAL, "TEXT", 15),
new DbColumn(KEY_ESP_PROPOSAL, "TEXT", 15),
new DbColumn(KEY_DNS_SERVERS, "TEXT", 17),
};
private static final String[] ALL_COLUMNS = getColumns(DATABASE_VERSION);
@ -243,6 +245,11 @@ public class VpnProfileDataSource
db.endTransaction();
}
}
if (oldVersion < 17)
{
db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_DNS_SERVERS +
" TEXT;");
}
}
private void updateColumns(SQLiteDatabase db, int version)
@ -448,6 +455,7 @@ public class VpnProfileDataSource
profile.setFlags(getInt(cursor, cursor.getColumnIndex(KEY_FLAGS)));
profile.setIkeProposal(cursor.getString(cursor.getColumnIndex(KEY_IKE_PROPOSAL)));
profile.setEspProposal(cursor.getString(cursor.getColumnIndex(KEY_ESP_PROPOSAL)));
profile.setDnsServers(cursor.getString(cursor.getColumnIndex(KEY_DNS_SERVERS)));
return profile;
}
@ -475,6 +483,7 @@ public class VpnProfileDataSource
values.put(KEY_FLAGS, profile.getFlags());
values.put(KEY_IKE_PROPOSAL, profile.getIkeProposal());
values.put(KEY_ESP_PROPOSAL, profile.getEspProposal());
values.put(KEY_DNS_SERVERS, profile.getDnsServers());
return values;
}

View File

@ -58,6 +58,7 @@ import org.strongswan.android.utils.Constants;
import org.strongswan.android.utils.IPRange;
import org.strongswan.android.utils.IPRangeSet;
import org.strongswan.android.utils.SettingsWriter;
import org.strongswan.android.utils.Utils;
import java.io.File;
import java.io.FileInputStream;
@ -838,8 +839,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
{
try
{
mBuilder.addDnsServer(address);
mCache.recordAddressFamily(address);
mCache.addDnsServer(address);
}
catch (IllegalArgumentException ex)
{
@ -1073,8 +1073,9 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
private final int mSplitTunneling;
private final SelectedAppsHandling mAppHandling;
private final SortedSet<String> mSelectedApps;
private final List<InetAddress> mDnsServers = new ArrayList<>();
private int mMtu;
private boolean mIPv4Seen, mIPv6Seen;
private boolean mIPv4Seen, mIPv6Seen, mDnsServersConfigured;
public BuilderCache(VpnProfile profile)
{
@ -1111,6 +1112,23 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
}
mAppHandling = appHandling;
if (profile.getDnsServers() != null)
{
for (String server : profile.getDnsServers().split("\\s+"))
{
try
{
mDnsServers.add(Utils.parseInetAddress(server));
recordAddressFamily(server);
mDnsServersConfigured = true;
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
}
}
/* set a default MTU, will be set by the daemon for regular interfaces */
Integer mtu = profile.getMTU();
mMtu = mtu == null ? Constants.MTU_MAX : mtu;
@ -1129,6 +1147,25 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
}
}
public void addDnsServer(String address)
{
/* ignore received DNS servers if any were configured */
if (mDnsServersConfigured)
{
return;
}
try
{
mDnsServers.add(Utils.parseInetAddress(address));
recordAddressFamily(address);
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
}
public void addRoute(String address, int prefixLength)
{
try
@ -1179,6 +1216,10 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
{
builder.addAddress(address.getFrom(), address.getPrefix());
}
for (InetAddress server : mDnsServers)
{
builder.addDnsServer(server);
}
/* add routes depending on whether split tunneling is allowed or not,
* that is, whether we have to handle and block non-VPN traffic */
if ((mSplitTunneling & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV4) == 0)
@ -1301,7 +1342,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
private boolean isIPv6(String address) throws UnknownHostException
{
InetAddress addr = InetAddress.getByName(address);
InetAddress addr = Utils.parseInetAddress(address);
if (addr instanceof Inet4Address)
{
return false;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2017 Tobias Brunner
* Copyright (C) 2012-2019 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
@ -72,6 +72,7 @@ import org.strongswan.android.utils.Constants;
import org.strongswan.android.utils.IPRangeSet;
import org.strongswan.android.utils.Utils;
import java.net.UnknownHostException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.SortedSet;
@ -138,6 +139,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
private EditText mEspProposal;
private TextView mProfileIdLabel;
private TextView mProfileId;
private MultiAutoCompleteTextView mDnsServers;
private TextInputLayoutHelper mDnsServersWrap;
@Override
public void onCreate(Bundle savedInstanceState)
@ -176,6 +179,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
mRemoteId = (MultiAutoCompleteTextView)findViewById(R.id.remote_id);
mRemoteIdWrap = (TextInputLayoutHelper) findViewById(R.id.remote_id_wrap);
mDnsServers = (MultiAutoCompleteTextView)findViewById(R.id.dns_servers);
mDnsServersWrap = (TextInputLayoutHelper) findViewById(R.id.dns_servers_wrap);
mMTU = (EditText)findViewById(R.id.mtu);
mMTUWrap = (TextInputLayoutHelper) findViewById(R.id.mtu_wrap);
mPort = (EditText)findViewById(R.id.port);
@ -573,7 +578,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
(flags != null && flags != 0) || (st != null && st != 0) ||
mProfile.getIncludedSubnets() != null || mProfile.getExcludedSubnets() != null ||
mProfile.getSelectedAppsHandling() != SelectedAppsHandling.SELECTED_APPS_DISABLE ||
mProfile.getIkeProposal() != null || mProfile.getEspProposal() != null;
mProfile.getIkeProposal() != null || mProfile.getEspProposal() != null ||
mProfile.getDnsServers() != null;
}
mShowAdvanced.setVisibility(!show ? View.VISIBLE : View.GONE);
mAdvancedSettings.setVisibility(show ? View.VISIBLE : View.GONE);
@ -683,6 +689,11 @@ public class VpnProfileDetailActivity extends AppCompatActivity
mEspProposalWrap.setError(getString(R.string.alert_text_no_proposal));
valid = false;
}
if (!validateAddresses(mDnsServers))
{
mDnsServersWrap.setError(getString(R.string.alert_text_no_ips));
valid = false;
}
return valid;
}
@ -737,6 +748,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
mProfile.setIkeProposal(ike.isEmpty() ? null : ike);
String esp = mEspProposal.getText().toString().trim();
mProfile.setEspProposal(esp.isEmpty() ? null : esp);
String dns = mDnsServers.getText().toString().trim();
mProfile.setDnsServers(dns.isEmpty() ? null : dns);
}
/**
@ -772,6 +785,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
mSelectedApps = mProfile.getSelectedAppsSet();
mIkeProposal.setText(mProfile.getIkeProposal());
mEspProposal.setText(mProfile.getEspProposal());
mDnsServers.setText(mProfile.getDnsServers());
mProfileId.setText(mProfile.getUUID().toString());
flags = mProfile.getFlags();
useralias = mProfile.getUserCertificateAlias();
@ -884,6 +898,32 @@ public class VpnProfileDetailActivity extends AppCompatActivity
return value.isEmpty() || IPRangeSet.fromString(value) != null;
}
/**
* Check that the value in the given text box is a valid list of IP addresses
*
* @param view text box
*/
private boolean validateAddresses(EditText view)
{
String value = view.getText().toString().trim();
if (value.isEmpty())
{
return true;
}
for (String addr : value.split("\\s+"))
{
try
{
Utils.parseInetAddress(addr);
}
catch (UnknownHostException e)
{
return false;
}
}
return true;
}
/**
* Check that the value in the given text box is a valid proposal
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Tobias Brunner
* Copyright (C) 2016-2019 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -74,6 +74,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.UUID;
import javax.net.ssl.SSLHandshakeException;
@ -522,6 +523,7 @@ public class VpnProfileImportActivity extends AppCompatActivity
profile.setIkeProposal(getProposal(obj, "ike-proposal", true));
profile.setEspProposal(getProposal(obj, "esp-proposal", false));
profile.setDnsServers(getAddressList(obj, "dns-servers"));
profile.setMTU(getInteger(obj, "mtu", Constants.MTU_MIN, Constants.MTU_MAX));
profile.setNATKeepAlive(getInteger(obj, "nat-keepalive", Constants.NAT_KEEPALIVE_MIN, Constants.NAT_KEEPALIVE_MAX));
JSONObject split = obj.optJSONObject("split-tunneling");
@ -605,6 +607,44 @@ public class VpnProfileImportActivity extends AppCompatActivity
return null;
}
private String getAddressList(JSONObject obj, String key) throws JSONException
{
ArrayList<String> addrs = new ArrayList<>();
JSONArray arr = obj.optJSONArray(key);
if (arr != null)
{
for (int i = 0; i < arr.length(); i++)
{
String addr = arr.getString(i).replace(" ", "");
addrs.add(addr);
}
}
else
{
String value = obj.optString(key, null);
if (!TextUtils.isEmpty(value))
{
Collections.addAll(addrs, value.split("\\s+"));
}
}
if (addrs.size() > 0)
{
for (String addr : addrs)
{
try
{
Utils.parseInetAddress(addr);
}
catch (UnknownHostException e)
{
throw new JSONException(getString(R.string.profile_import_failed_value, key));
}
}
return TextUtils.join(" ", addrs);
}
return null;
}
private String getApps(JSONArray arr) throws JSONException
{
ArrayList<String> apps = new ArrayList<>();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2012-2019 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
@ -49,6 +49,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
public class VpnProfileListFragment extends Fragment
{
@ -230,11 +231,13 @@ public class VpnProfileListFragment extends Fragment
private final MultiChoiceModeListener mVpnProfileSelected = new MultiChoiceModeListener() {
private MenuItem mEditProfile;
private MenuItem mCopyProfile;
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
{
mEditProfile.setEnabled(mSelected.size() == 1);
mCopyProfile.setEnabled(mEditProfile.isEnabled());
return true;
}
@ -250,6 +253,7 @@ public class VpnProfileListFragment extends Fragment
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.profile_list_context, menu);
mEditProfile = menu.findItem(R.id.edit_profile);
mCopyProfile = menu.findItem(R.id.copy_profile);
mode.setTitle(R.string.select_profiles);
return true;
}
@ -268,6 +272,24 @@ public class VpnProfileListFragment extends Fragment
startActivityForResult(connectionIntent, EDIT_REQUEST);
break;
}
case R.id.copy_profile:
{
int position = mSelected.iterator().next();
VpnProfile profile = (VpnProfile)mListView.getItemAtPosition(position);
profile = profile.clone();
profile.setUUID(UUID.randomUUID());
profile.setName(String.format(getString(R.string.copied_name), profile.getName()));
mDataSource.insertProfile(profile);
Intent intent = new Intent(Constants.VPN_PROFILES_CHANGED);
intent.putExtra(Constants.VPN_PROFILES_SINGLE, profile.getId());
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);
Intent connectionIntent = new Intent(getActivity(), VpnProfileDetailActivity.class);
connectionIntent.putExtra(VpnProfileDataSource.KEY_ID, profile.getId());
startActivityForResult(connectionIntent, EDIT_REQUEST);
break;
}
case R.id.delete_profile:
{
ArrayList<VpnProfile> profiles = new ArrayList<>();

View File

@ -76,7 +76,7 @@ public class IPRange implements Comparable<IPRange>
public IPRange(String from, String to) throws UnknownHostException
{
this(InetAddress.getByName(from), InetAddress.getByName(to));
this(Utils.parseInetAddress(from), Utils.parseInetAddress(to));
}
public IPRange(InetAddress from, InetAddress to)
@ -106,7 +106,7 @@ public class IPRange implements Comparable<IPRange>
public IPRange(String base, int prefix) throws UnknownHostException
{
this(InetAddress.getByName(base), prefix);
this(Utils.parseInetAddress(base), prefix);
}
public IPRange(InetAddress base, int prefix)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Tobias Brunner
* Copyright (C) 2014-2019 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -16,6 +16,9 @@
package org.strongswan.android.utils;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Utils
{
static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
@ -46,4 +49,29 @@ public class Utils
* @return true if valid
*/
public native static boolean isProposalValid(boolean ike, String proposal);
/**
* Parse an IP address without doing a name lookup
*
* @param address IP address string
* @return address bytes if valid
*/
private native static byte[] parseInetAddressBytes(String address);
/**
* Parse an IP address without doing a name lookup (as compared to InetAddress.fromName())
*
* @param address IP address string
* @return address if valid
* @throws UnknownHostException if address is invalid
*/
public static InetAddress parseInetAddress(String address) throws UnknownHostException
{
byte[] bytes = parseInetAddressBytes(address);
if (bytes == null)
{
throw new UnknownHostException();
}
return InetAddress.getByAddress(bytes);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2012-2019 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
@ -758,3 +758,34 @@ JNI_METHOD_P(org_strongswan_android_utils, Utils, isProposalValid, jboolean,
library_deinit();
return valid;
}
/**
* Utility function to parse an IP address from a string (static, so `this` is the class)
*/
JNI_METHOD_P(org_strongswan_android_utils, Utils, parseInetAddressBytes, jbyteArray,
jstring address)
{
jbyteArray bytes;
host_t *host;
char *str;
dbg = dbg_android;
if (!library_init(NULL, "charon"))
{
library_deinit();
return NULL;
}
str = androidjni_convert_jstring(env, address);
host = host_create_from_string(str, 0);
if (!host)
{
free(str);
return NULL;
}
bytes = byte_array_from_chunk(env, host->get_address(host));
host->destroy(host);
free(str);
library_deinit();
return bytes;
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012-2018 Tobias Brunner
Copyright (C) 2012-2019 Tobias Brunner
Copyright (C) 2012 Giuliano Grassi
Copyright (C) 2012 Ralf Sager
HSR Hochschule fuer Technik Rapperswil
@ -212,6 +212,24 @@
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
<org.strongswan.android.ui.widget.TextInputLayoutHelper
android:id="@+id/dns_servers_wrap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="@string/profile_dns_servers_label"
app:helper_text="@string/profile_dns_servers_hint" >
<MultiAutoCompleteTextView
android:id="@+id/dns_servers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="textNoSuggestions"
android:completionThreshold="1" />
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
<org.strongswan.android.ui.widget.TextInputLayoutHelper
android:id="@+id/mtu_wrap"
android:layout_width="match_parent"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 Tobias Brunner
Copyright (C) 2012-2019 Tobias Brunner
HSR Hochschule fuer Technik Rapperswil
This program is free software; you can redistribute it and/or modify it
@ -18,6 +18,9 @@
<item android:id="@+id/edit_profile"
android:title="@string/edit_profile" />
<item android:id="@+id/copy_profile"
android:title="@string/copy_profile" />
<item android:id="@+id/delete_profile"
android:title="@string/delete_profile" />

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012-2018 Tobias Brunner
Copyright (C) 2012-2019 Tobias Brunner
Copyright (C) 2012 Giuliano Grassi
Copyright (C) 2012 Ralf Sager
HSR Hochschule fuer Technik Rapperswil
@ -47,6 +47,8 @@
<string name="no_profiles">Keine VPN Profile vorhanden.</string>
<string name="add_profile">Profil hinzufügen</string>
<string name="edit_profile">Bearbeiten</string>
<string name="copy_profile">Kopieren</string>
<string name="copied_name">%1$s (Kopie)</string>
<string name="delete_profile">Löschen</string>
<string name="select_profiles">Profile auswählen</string>
<string name="profiles_deleted">Ausgewählte Profile gelöscht</string>
@ -83,6 +85,8 @@
<string name="profile_remote_id_label">Server-Identität</string>
<string name="profile_remote_id_hint">Standardwert ist der konfigurierte Server. Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen</string>
<string name="profile_remote_id_hint_gateway">Standardwert ist \"%1$s\". Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen</string>
<string name="profile_dns_servers_label">DNS Server</string>
<string name="profile_dns_servers_hint">Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\", standardmässig werden die vom VPN Server erhaltenen Server verwendet)</string>
<string name="profile_mtu_label">MTU des VPN Tunnel-Device</string>
<string name="profile_mtu_hint">Falls der Standardwert in einem bestimmten Netzwerk nicht geeignet ist</string>
<string name="profile_port_label">Server Port</string>
@ -136,6 +140,7 @@
<string name="alert_text_nocertfound">Bitte wählen Sie eines aus oder aktivieren Sie <i>Automatisch wählen</i></string>
<string name="alert_text_out_of_range">Bitte geben Sie eine Nummer von %1$d - %2$d ein</string>
<string name="alert_text_no_subnets">Bitte geben Sie mit Leerzeichen getrennte, gültige Subnetzte und/oder IP-Adressen ein</string>
<string name="alert_text_no_ips">Bitte geben Sie mit Leerzeichen getrennte, gültige IP-Adressen ein</string>
<string name="alert_text_no_proposal">Bitte geben Sie eine mit Bindestrichen getrennte, gültige Liste von Algorithmen ein</string>
<string name="tnc_notice_title">EAP-TNC kann Ihre Privatsphäre beeinträchtigen</string>
<string name="tnc_notice_subtitle">Gerätedaten werden an den Server-Betreiber gesendet</string>

View File

@ -47,6 +47,8 @@
<string name="no_profiles">Brak profilu VPN</string>
<string name="add_profile">Dodaj profil VPN</string>
<string name="edit_profile">Edytuj</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">Usuń</string>
<string name="select_profiles">Wybierz profile</string>
<string name="profiles_deleted">Wybrane profile usunięte</string>
@ -83,6 +85,8 @@
<string name="profile_remote_id_label">Server identity</string>
<string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_dns_servers_label">DNS servers</string>
<string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
<string name="profile_mtu_label">MTU of the VPN tunnel device</string>
<string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
<string name="profile_port_label">Server port</string>
@ -136,6 +140,7 @@
<string name="alert_text_nocertfound">Wybierz lub uaktywnij jeden <i>Wybierz automatycznie</i></string>
<string name="alert_text_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
<string name="tnc_notice_subtitle">Device data is sent to the server operator</string>

View File

@ -44,6 +44,8 @@
<string name="no_profiles">VPN профили не обнаружены.</string>
<string name="add_profile">Добавить VPN профиль</string>
<string name="edit_profile">Редактировать</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">Удалить</string>
<string name="select_profiles">Выбрать профили</string>
<string name="profiles_deleted">Выбранные профили удалены</string>
@ -80,6 +82,8 @@
<string name="profile_remote_id_label">Server identity</string>
<string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_dns_servers_label">DNS servers</string>
<string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
<string name="profile_mtu_label">MTU of the VPN tunnel device</string>
<string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
<string name="profile_port_label">Server port</string>
@ -133,6 +137,7 @@
<string name="alert_text_nocertfound">Пожалуйста выберите один <i>Выбрать автоматически</i></string>
<string name="alert_text_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
<string name="tnc_notice_subtitle">Device data is sent to the server operator</string>

View File

@ -45,6 +45,8 @@
<string name="no_profiles">Немає VPN профілів</string>
<string name="add_profile">Додати VPN профіль</string>
<string name="edit_profile">Редагувати</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">Видалити</string>
<string name="select_profiles">Обрати профіль</string>
<string name="profiles_deleted">Обрані профілі видалено</string>
@ -81,6 +83,8 @@
<string name="profile_remote_id_label">Server identity</string>
<string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_dns_servers_label">DNS servers</string>
<string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
<string name="profile_mtu_label">MTU of the VPN tunnel device</string>
<string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
<string name="profile_port_label">Server port</string>
@ -134,6 +138,7 @@
<string name="alert_text_nocertfound">Будь ласка виберіть один <i>Вибрати автоматично</i></string>
<string name="alert_text_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
<string name="tnc_notice_subtitle">Device data is sent to the server operator</string>

View File

@ -44,6 +44,8 @@
<string name="no_profiles">无配置.</string>
<string name="add_profile">添加VPN配置</string>
<string name="edit_profile">编辑</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">删除</string>
<string name="select_profiles">选择配置</string>
<string name="profiles_deleted">所选配置已删除</string>
@ -133,6 +135,7 @@
<string name="alert_text_nocertfound">请选择一项或激活 <i>自动选择</i></string>
<string name="alert_text_out_of_range">请输入一个数字范围从%1$d到%2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC可能会影响您的隐私</string>
<string name="tnc_notice_subtitle">设备数据已被发送至服务器管理员</string>

View File

@ -44,6 +44,8 @@
<string name="no_profiles">沒有設定檔</string>
<string name="add_profile">新增VPN設定檔</string>
<string name="edit_profile">編輯</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">刪除</string>
<string name="select_profiles">選擇設定檔</string>
<string name="profiles_deleted">選擇的設定檔已經刪除</string>
@ -80,6 +82,8 @@
<string name="profile_remote_id_label">伺服器ID</string>
<string name="profile_remote_id_hint">預設為已設定的伺服器位置。自訂值會在授權期間送到伺服器</string>
<string name="profile_remote_id_hint_gateway">預設為 \"%1$s\"。自訂值會在授權期間送到伺服器</string>
<string name="profile_dns_servers_label">DNS servers</string>
<string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
<string name="profile_mtu_label">VPN通道裝置的MTU值</string>
<string name="profile_mtu_hint">如果在某個網路下預設值不適合</string>
<string name="profile_port_label">伺服器Port</string>
@ -133,6 +137,7 @@
<string name="alert_text_nocertfound">請選擇一項或啟動 <i>自動選擇</i></string>
<string name="alert_text_out_of_range">請輸入一個數字範圍從%1$d到%2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC可能會影響您的隱私安全</string>
<string name="tnc_notice_subtitle">裝置資料已經發送給伺服器管理者</string>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012-2018 Tobias Brunner
Copyright (C) 2012-2019 Tobias Brunner
Copyright (C) 2012 Giuliano Grassi
Copyright (C) 2012 Ralf Sager
HSR Hochschule fuer Technik Rapperswil
@ -47,6 +47,8 @@
<string name="no_profiles">No VPN profiles.</string>
<string name="add_profile">Add VPN profile</string>
<string name="edit_profile">Edit</string>
<string name="copy_profile">Copy</string>
<string name="copied_name">%1$s (Copy)</string>
<string name="delete_profile">Delete</string>
<string name="select_profiles">Select profiles</string>
<string name="profiles_deleted">Selected profiles deleted</string>
@ -83,6 +85,8 @@
<string name="profile_remote_id_label">Server identity</string>
<string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
<string name="profile_dns_servers_label">DNS servers</string>
<string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
<string name="profile_mtu_label">MTU of the VPN tunnel device</string>
<string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
<string name="profile_port_label">Server port</string>
@ -136,6 +140,7 @@
<string name="alert_text_nocertfound">Please select one or activate <i>Select automatically</i></string>
<string name="alert_text_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
<string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
<string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
<string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
<string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
<string name="tnc_notice_subtitle">Device data is sent to the server operator</string>

View File

@ -4,7 +4,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.android.tools.build:gradle:3.3.2'
}
}

View File

@ -1,6 +1,6 @@
#Mon Jun 04 11:56:43 CEST 2018
#Mon Mar 04 17:15:25 CET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip