Merge branch 'android-gui-updates'
Removes the progress dialogs while connecting/disconnecting, updates the VPN profile editor (floating labels, helper texts) and allows configuration of the remote identity (disables loose identity matching), and selection of the local identity if certificates are used. Also fixes an issue when redirected during IKE_AUTH and increases the NAT-T keepalive interval. Fixes #1403.
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
To build this within the NDK several things have to be added in the
|
To build this within the NDK the following things have to be done:
|
||||||
app/src/main/jni/ folder:
|
|
||||||
|
|
||||||
- strongswan: The strongSwan sources. This can either be an extracted tarball,
|
- By default the strongSwan sources of the current Git tree are used. They have
|
||||||
or a symlink to the Git repository. To build from the repository the sources
|
to be prepared first (see HACKING for a list of required tools):
|
||||||
have to be prepared first (see HACKING for a list of required tools):
|
|
||||||
|
|
||||||
./autogen.sh && ./configure && make && make distclean
|
./autogen.sh && ./configure && make && make distclean
|
||||||
|
|
||||||
- openssl: The OpenSSL sources. Since the sources need to be changed to be
|
It is also possible to use the sources from a different directory (e.g. an
|
||||||
built on Android (and especially in the NDK), we provide a modified mirror
|
extracted tarball) by setting strongswan_DIR in app/src/main/jni/Android.mk.
|
||||||
of the official Android OpenSSL version on git.strongswan.org.
|
|
||||||
|
|
||||||
|
- The OpenSSL or BoringSSL sources are expected in app/src/main/jni/openssl.
|
||||||
|
Since the sources need to be changed to be built on Android (and especially
|
||||||
|
in the NDK) we provide a modified mirror of the official Android repositories
|
||||||
|
on git.strongswan.org.
|
||||||
|
|||||||
+23
-2
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -25,6 +25,7 @@ public class VpnProfile implements Cloneable
|
|||||||
public static final int SPLIT_TUNNELING_BLOCK_IPV6 = 2;
|
public static final int SPLIT_TUNNELING_BLOCK_IPV6 = 2;
|
||||||
|
|
||||||
private String mName, mGateway, mUsername, mPassword, mCertificate, mUserCertificate;
|
private String mName, mGateway, mUsername, mPassword, mCertificate, mUserCertificate;
|
||||||
|
private String mRemoteId, mLocalId;
|
||||||
private Integer mMTU, mPort, mSplitTunneling;
|
private Integer mMTU, mPort, mSplitTunneling;
|
||||||
private VpnType mVpnType;
|
private VpnType mVpnType;
|
||||||
private long mId = -1;
|
private long mId = -1;
|
||||||
@@ -109,6 +110,26 @@ public class VpnProfile implements Cloneable
|
|||||||
this.mUserCertificate = alias;
|
this.mUserCertificate = alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLocalId()
|
||||||
|
{
|
||||||
|
return mLocalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalId(String localId)
|
||||||
|
{
|
||||||
|
this.mLocalId = localId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemoteId()
|
||||||
|
{
|
||||||
|
return mRemoteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemoteId(String remoteId)
|
||||||
|
{
|
||||||
|
this.mRemoteId = remoteId;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getMTU()
|
public Integer getMTU()
|
||||||
{
|
{
|
||||||
return mMTU;
|
return mMTU;
|
||||||
|
|||||||
+21
-4
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -43,6 +43,8 @@ public class VpnProfileDataSource
|
|||||||
public static final String KEY_MTU = "mtu";
|
public static final String KEY_MTU = "mtu";
|
||||||
public static final String KEY_PORT = "port";
|
public static final String KEY_PORT = "port";
|
||||||
public static final String KEY_SPLIT_TUNNELING = "split_tunneling";
|
public static final String KEY_SPLIT_TUNNELING = "split_tunneling";
|
||||||
|
public static final String KEY_LOCAL_ID = "local_id";
|
||||||
|
public static final String KEY_REMOTE_ID = "remote_id";
|
||||||
|
|
||||||
private DatabaseHelper mDbHelper;
|
private DatabaseHelper mDbHelper;
|
||||||
private SQLiteDatabase mDatabase;
|
private SQLiteDatabase mDatabase;
|
||||||
@@ -51,7 +53,7 @@ public class VpnProfileDataSource
|
|||||||
private static final String DATABASE_NAME = "strongswan.db";
|
private static final String DATABASE_NAME = "strongswan.db";
|
||||||
private static final String TABLE_VPNPROFILE = "vpnprofile";
|
private static final String TABLE_VPNPROFILE = "vpnprofile";
|
||||||
|
|
||||||
private static final int DATABASE_VERSION = 7;
|
private static final int DATABASE_VERSION = 8;
|
||||||
|
|
||||||
public static final String DATABASE_CREATE =
|
public static final String DATABASE_CREATE =
|
||||||
"CREATE TABLE " + TABLE_VPNPROFILE + " (" +
|
"CREATE TABLE " + TABLE_VPNPROFILE + " (" +
|
||||||
@@ -65,7 +67,9 @@ public class VpnProfileDataSource
|
|||||||
KEY_USER_CERTIFICATE + " TEXT," +
|
KEY_USER_CERTIFICATE + " TEXT," +
|
||||||
KEY_MTU + " INTEGER," +
|
KEY_MTU + " INTEGER," +
|
||||||
KEY_PORT + " INTEGER," +
|
KEY_PORT + " INTEGER," +
|
||||||
KEY_SPLIT_TUNNELING + " INTEGER" +
|
KEY_SPLIT_TUNNELING + " INTEGER," +
|
||||||
|
KEY_LOCAL_ID + " TEXT," +
|
||||||
|
KEY_REMOTE_ID + " TEXT" +
|
||||||
");";
|
");";
|
||||||
private static final String[] ALL_COLUMNS = new String[] {
|
private static final String[] ALL_COLUMNS = new String[] {
|
||||||
KEY_ID,
|
KEY_ID,
|
||||||
@@ -79,6 +83,8 @@ public class VpnProfileDataSource
|
|||||||
KEY_MTU,
|
KEY_MTU,
|
||||||
KEY_PORT,
|
KEY_PORT,
|
||||||
KEY_SPLIT_TUNNELING,
|
KEY_SPLIT_TUNNELING,
|
||||||
|
KEY_LOCAL_ID,
|
||||||
|
KEY_REMOTE_ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static class DatabaseHelper extends SQLiteOpenHelper
|
private static class DatabaseHelper extends SQLiteOpenHelper
|
||||||
@@ -128,6 +134,13 @@ public class VpnProfileDataSource
|
|||||||
db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SPLIT_TUNNELING +
|
db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SPLIT_TUNNELING +
|
||||||
" INTEGER;");
|
" INTEGER;");
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 8)
|
||||||
|
{
|
||||||
|
db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_LOCAL_ID +
|
||||||
|
" TEXT;");
|
||||||
|
db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_REMOTE_ID +
|
||||||
|
" TEXT;");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateColumns(SQLiteDatabase db)
|
private void updateColumns(SQLiteDatabase db)
|
||||||
@@ -282,6 +295,8 @@ public class VpnProfileDataSource
|
|||||||
profile.setMTU(getInt(cursor, cursor.getColumnIndex(KEY_MTU)));
|
profile.setMTU(getInt(cursor, cursor.getColumnIndex(KEY_MTU)));
|
||||||
profile.setPort(getInt(cursor, cursor.getColumnIndex(KEY_PORT)));
|
profile.setPort(getInt(cursor, cursor.getColumnIndex(KEY_PORT)));
|
||||||
profile.setSplitTunneling(getInt(cursor, cursor.getColumnIndex(KEY_SPLIT_TUNNELING)));
|
profile.setSplitTunneling(getInt(cursor, cursor.getColumnIndex(KEY_SPLIT_TUNNELING)));
|
||||||
|
profile.setLocalId(cursor.getString(cursor.getColumnIndex(KEY_LOCAL_ID)));
|
||||||
|
profile.setRemoteId(cursor.getString(cursor.getColumnIndex(KEY_REMOTE_ID)));
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,6 +313,8 @@ public class VpnProfileDataSource
|
|||||||
values.put(KEY_MTU, profile.getMTU());
|
values.put(KEY_MTU, profile.getMTU());
|
||||||
values.put(KEY_PORT, profile.getPort());
|
values.put(KEY_PORT, profile.getPort());
|
||||||
values.put(KEY_SPLIT_TUNNELING, profile.getSplitTunneling());
|
values.put(KEY_SPLIT_TUNNELING, profile.getSplitTunneling());
|
||||||
|
values.put(KEY_LOCAL_ID, profile.getLocalId());
|
||||||
|
values.put(KEY_REMOTE_ID, profile.getRemoteId());
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -232,6 +232,8 @@ public class CharonVpnService extends VpnService implements Runnable
|
|||||||
writer.setValue("connection.port", mCurrentProfile.getPort());
|
writer.setValue("connection.port", mCurrentProfile.getPort());
|
||||||
writer.setValue("connection.username", mCurrentProfile.getUsername());
|
writer.setValue("connection.username", mCurrentProfile.getUsername());
|
||||||
writer.setValue("connection.password", mCurrentProfile.getPassword());
|
writer.setValue("connection.password", mCurrentProfile.getPassword());
|
||||||
|
writer.setValue("connection.local_id", mCurrentProfile.getLocalId());
|
||||||
|
writer.setValue("connection.remote_id", mCurrentProfile.getRemoteId());
|
||||||
initiate(writer.serialize());
|
initiate(writer.serialize());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+43
-4
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -15,10 +15,15 @@
|
|||||||
|
|
||||||
package org.strongswan.android.security;
|
package org.strongswan.android.security;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import android.net.http.SslCertificate;
|
import android.net.http.SslCertificate;
|
||||||
|
|
||||||
|
import java.security.cert.CertificateParsingException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class TrustedCertificateEntry implements Comparable<TrustedCertificateEntry>
|
public class TrustedCertificateEntry implements Comparable<TrustedCertificateEntry>
|
||||||
{
|
{
|
||||||
private final X509Certificate mCert;
|
private final X509Certificate mCert;
|
||||||
@@ -86,6 +91,40 @@ public class TrustedCertificateEntry implements Comparable<TrustedCertificateEnt
|
|||||||
return mSubjectSecondary;
|
return mSubjectSecondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a sorted list of all rfc822Name, dnSName and iPAddress subjectAltNames
|
||||||
|
*
|
||||||
|
* @return sorted list of selected SANs
|
||||||
|
*/
|
||||||
|
public List<String> getSubjectAltNames()
|
||||||
|
{
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Collection<List<?>> sans = mCert.getSubjectAlternativeNames();
|
||||||
|
if (sans != null)
|
||||||
|
{
|
||||||
|
for (List<?> san : sans)
|
||||||
|
{
|
||||||
|
switch ((Integer)san.get(0))
|
||||||
|
{
|
||||||
|
case 1: /* rfc822Name */
|
||||||
|
case 2: /* dnSName */
|
||||||
|
case 7: /* iPAddress */
|
||||||
|
list.add((String)san.get(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(list);
|
||||||
|
}
|
||||||
|
catch(CertificateParsingException ex)
|
||||||
|
{
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The alias associated with this certificate.
|
* The alias associated with this certificate.
|
||||||
*
|
*
|
||||||
|
|||||||
+7
-8
@@ -15,9 +15,6 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.app.FragmentTransaction;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -25,6 +22,9 @@ import android.content.Intent;
|
|||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -66,7 +66,6 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
|
|||||||
{
|
{
|
||||||
mService = ((VpnStateService.LocalBinder)service).getService();
|
mService = ((VpnStateService.LocalBinder)service).getService();
|
||||||
mService.registerListener(ImcStateFragment.this);
|
mService.registerListener(ImcStateFragment.this);
|
||||||
updateView();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,9 +146,9 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart()
|
public void onResume()
|
||||||
{
|
{
|
||||||
super.onStart();
|
super.onResume();
|
||||||
if (mService != null)
|
if (mService != null)
|
||||||
{
|
{
|
||||||
mService.registerListener(this);
|
mService.registerListener(this);
|
||||||
@@ -158,9 +157,9 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop()
|
public void onPause()
|
||||||
{
|
{
|
||||||
super.onStop();
|
super.onPause();
|
||||||
if (mService != null)
|
if (mService != null)
|
||||||
{
|
{
|
||||||
mService.unregisterListener(this);
|
mService.unregisterListener(this);
|
||||||
|
|||||||
+12
-12
@@ -15,24 +15,24 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.FileObserver;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.logic.CharonVpnService;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
|
||||||
import org.strongswan.android.logic.CharonVpnService;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.FileObserver;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
public class LogFragment extends Fragment implements Runnable
|
public class LogFragment extends Fragment implements Runnable
|
||||||
{
|
{
|
||||||
private String mLogFilePath;
|
private String mLogFilePath;
|
||||||
|
|||||||
@@ -18,9 +18,6 @@
|
|||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.app.FragmentTransaction;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -31,6 +28,9 @@ import android.net.VpnService;
|
|||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
@@ -230,7 +230,7 @@ public class MainActivity extends AppCompatActivity implements OnVpnProfileSelec
|
|||||||
|
|
||||||
removeFragmentByTag(DIALOG_TAG);
|
removeFragmentByTag(DIALOG_TAG);
|
||||||
|
|
||||||
if (mService != null && mService.getState() == State.CONNECTED)
|
if (mService != null && (mService.getState() == State.CONNECTED || mService.getState() == State.CONNECTING))
|
||||||
{
|
{
|
||||||
profileInfo.putBoolean(PROFILE_RECONNECT, mService.getProfile().getId() == profile.getId());
|
profileInfo.putBoolean(PROFILE_RECONNECT, mService.getProfile().getId() == profile.getId());
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ public class MainActivity extends AppCompatActivity implements OnVpnProfileSelec
|
|||||||
*/
|
*/
|
||||||
public void removeFragmentByTag(String tag)
|
public void removeFragmentByTag(String tag)
|
||||||
{
|
{
|
||||||
FragmentManager fm = getFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
Fragment login = fm.findFragmentByTag(tag);
|
Fragment login = fm.findFragmentByTag(tag);
|
||||||
if (login != null)
|
if (login != null)
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Tobias Brunner
|
* Copyright (C) 2013-2016 Tobias Brunner
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -15,17 +15,18 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
|
||||||
import org.strongswan.android.logic.imc.RemediationInstruction;
|
|
||||||
|
|
||||||
import android.app.ListFragment;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.ListFragment;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.logic.imc.RemediationInstruction;
|
||||||
|
|
||||||
public class RemediationInstructionFragment extends ListFragment
|
public class RemediationInstructionFragment extends ListFragment
|
||||||
{
|
{
|
||||||
public static final String ARG_REMEDIATION_INSTRUCTION = "instruction";
|
public static final String ARG_REMEDIATION_INSTRUCTION = "instruction";
|
||||||
@@ -37,7 +38,13 @@ public class RemediationInstructionFragment extends ListFragment
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
return inflater.inflate(R.layout.remediation_instruction, container, false);
|
/* while the documentation recommends to include "@android:layout/list_content" to retain
|
||||||
|
* the default functionality, this does not actually work with the ListFragment provided by
|
||||||
|
* the support library as it builds the view manually and uses different IDs */
|
||||||
|
View layout = inflater.inflate(R.layout.remediation_instruction, container, false);
|
||||||
|
FrameLayout list = (FrameLayout)layout.findViewById(R.id.list_container);
|
||||||
|
list.addView(super.onCreateView(inflater, list, savedInstanceState));
|
||||||
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+5
-5
@@ -38,7 +38,7 @@ public class RemediationInstructionsActivity extends AppCompatActivity implement
|
|||||||
{ /* only update if we're not restoring */
|
{ /* only update if we're not restoring */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RemediationInstructionsFragment frag = (RemediationInstructionsFragment)getFragmentManager().findFragmentById(R.id.remediation_instructions_fragment);
|
RemediationInstructionsFragment frag = (RemediationInstructionsFragment)getSupportFragmentManager().findFragmentById(R.id.remediation_instructions_fragment);
|
||||||
if (frag != null)
|
if (frag != null)
|
||||||
{ /* two-pane layout, update fragment */
|
{ /* two-pane layout, update fragment */
|
||||||
Bundle extras = getIntent().getExtras();
|
Bundle extras = getIntent().getExtras();
|
||||||
@@ -49,7 +49,7 @@ public class RemediationInstructionsActivity extends AppCompatActivity implement
|
|||||||
{ /* one-pane layout, create fragment */
|
{ /* one-pane layout, create fragment */
|
||||||
frag = new RemediationInstructionsFragment();
|
frag = new RemediationInstructionsFragment();
|
||||||
frag.setArguments(getIntent().getExtras());
|
frag.setArguments(getIntent().getExtras());
|
||||||
getFragmentManager().beginTransaction().add(R.id.fragment_container, frag).commit();
|
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, frag).commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class RemediationInstructionsActivity extends AppCompatActivity implement
|
|||||||
{
|
{
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
/* one-pane layout, pop possible fragment from stack, finish otherwise */
|
/* one-pane layout, pop possible fragment from stack, finish otherwise */
|
||||||
if (!getFragmentManager().popBackStackImmediate())
|
if (!getSupportFragmentManager().popBackStackImmediate())
|
||||||
{
|
{
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ public class RemediationInstructionsActivity extends AppCompatActivity implement
|
|||||||
@Override
|
@Override
|
||||||
public void onRemediationInstructionSelected(RemediationInstruction instruction)
|
public void onRemediationInstructionSelected(RemediationInstruction instruction)
|
||||||
{
|
{
|
||||||
RemediationInstructionFragment frag = (RemediationInstructionFragment)getFragmentManager().findFragmentById(R.id.remediation_instruction_fragment);
|
RemediationInstructionFragment frag = (RemediationInstructionFragment)getSupportFragmentManager().findFragmentById(R.id.remediation_instruction_fragment);
|
||||||
|
|
||||||
if (frag != null)
|
if (frag != null)
|
||||||
{ /* two-pane layout, update directly */
|
{ /* two-pane layout, update directly */
|
||||||
@@ -87,7 +87,7 @@ public class RemediationInstructionsActivity extends AppCompatActivity implement
|
|||||||
args.putParcelable(RemediationInstructionFragment.ARG_REMEDIATION_INSTRUCTION, instruction);
|
args.putParcelable(RemediationInstructionFragment.ARG_REMEDIATION_INSTRUCTION, instruction);
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
getFragmentManager().beginTransaction().replace(R.id.fragment_container, frag).addToBackStack(null).commit();
|
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, frag).addToBackStack(null).commit();
|
||||||
getSupportActionBar().setTitle(instruction.getTitle());
|
getSupportActionBar().setTitle(instruction.getTitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -15,17 +15,17 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.ListFragment;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
import org.strongswan.android.R;
|
||||||
import org.strongswan.android.logic.imc.RemediationInstruction;
|
import org.strongswan.android.logic.imc.RemediationInstruction;
|
||||||
import org.strongswan.android.ui.adapter.RemediationInstructionAdapter;
|
import org.strongswan.android.ui.adapter.RemediationInstructionAdapter;
|
||||||
|
|
||||||
import android.app.Activity;
|
import java.util.ArrayList;
|
||||||
import android.app.ListFragment;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
public class RemediationInstructionsFragment extends ListFragment
|
public class RemediationInstructionsFragment extends ListFragment
|
||||||
{
|
{
|
||||||
@@ -65,13 +65,13 @@ public class RemediationInstructionsFragment extends ListFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity)
|
public void onAttach(Context context)
|
||||||
{
|
{
|
||||||
super.onAttach(activity);
|
super.onAttach(context);
|
||||||
|
|
||||||
if (activity instanceof OnRemediationInstructionSelectedListener)
|
if (context instanceof OnRemediationInstructionSelectedListener)
|
||||||
{
|
{
|
||||||
mListener = (OnRemediationInstructionSelectedListener)activity;
|
mListener = (OnRemediationInstructionSelectedListener)context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+167
-11
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2014 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -29,7 +29,12 @@ import android.security.KeyChainException;
|
|||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.app.AppCompatDialogFragment;
|
import android.support.v7.app.AppCompatDialogFragment;
|
||||||
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -39,10 +44,12 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.MultiAutoCompleteTextView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -54,6 +61,8 @@ import org.strongswan.android.data.VpnType;
|
|||||||
import org.strongswan.android.data.VpnType.VpnTypeFeature;
|
import org.strongswan.android.data.VpnType.VpnTypeFeature;
|
||||||
import org.strongswan.android.logic.TrustedCertificateManager;
|
import org.strongswan.android.logic.TrustedCertificateManager;
|
||||||
import org.strongswan.android.security.TrustedCertificateEntry;
|
import org.strongswan.android.security.TrustedCertificateEntry;
|
||||||
|
import org.strongswan.android.ui.adapter.CertificateIdentitiesAdapter;
|
||||||
|
import org.strongswan.android.ui.widget.TextInputLayoutHelper;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
@@ -67,24 +76,34 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
private Long mId;
|
private Long mId;
|
||||||
private TrustedCertificateEntry mCertEntry;
|
private TrustedCertificateEntry mCertEntry;
|
||||||
private String mUserCertLoading;
|
private String mUserCertLoading;
|
||||||
|
private CertificateIdentitiesAdapter mSelectUserIdAdapter;
|
||||||
|
private String mSelectedUserId;
|
||||||
private TrustedCertificateEntry mUserCertEntry;
|
private TrustedCertificateEntry mUserCertEntry;
|
||||||
private VpnType mVpnType = VpnType.IKEV2_EAP;
|
private VpnType mVpnType = VpnType.IKEV2_EAP;
|
||||||
private VpnProfile mProfile;
|
private VpnProfile mProfile;
|
||||||
private EditText mName;
|
private MultiAutoCompleteTextView mName;
|
||||||
|
private TextInputLayoutHelper mNameWrap;
|
||||||
private EditText mGateway;
|
private EditText mGateway;
|
||||||
|
private TextInputLayoutHelper mGatewayWrap;
|
||||||
private Spinner mSelectVpnType;
|
private Spinner mSelectVpnType;
|
||||||
private ViewGroup mUsernamePassword;
|
private ViewGroup mUsernamePassword;
|
||||||
private EditText mUsername;
|
private EditText mUsername;
|
||||||
|
private TextInputLayoutHelper mUsernameWrap;
|
||||||
private EditText mPassword;
|
private EditText mPassword;
|
||||||
private ViewGroup mUserCertificate;
|
private ViewGroup mUserCertificate;
|
||||||
private RelativeLayout mSelectUserCert;
|
private RelativeLayout mSelectUserCert;
|
||||||
|
private Spinner mSelectUserId;
|
||||||
private CheckBox mCheckAuto;
|
private CheckBox mCheckAuto;
|
||||||
private RelativeLayout mSelectCert;
|
private RelativeLayout mSelectCert;
|
||||||
private RelativeLayout mTncNotice;
|
private RelativeLayout mTncNotice;
|
||||||
private CheckBox mShowAdvanced;
|
private CheckBox mShowAdvanced;
|
||||||
private ViewGroup mAdvancedSettings;
|
private ViewGroup mAdvancedSettings;
|
||||||
|
private MultiAutoCompleteTextView mRemoteId;
|
||||||
|
private TextInputLayoutHelper mRemoteIdWrap;
|
||||||
private EditText mMTU;
|
private EditText mMTU;
|
||||||
|
private TextInputLayoutHelper mMTUWrap;
|
||||||
private EditText mPort;
|
private EditText mPort;
|
||||||
|
private TextInputLayoutHelper mPortWrap;
|
||||||
private CheckBox mBlockIPv4;
|
private CheckBox mBlockIPv4;
|
||||||
private CheckBox mBlockIPv6;
|
private CheckBox mBlockIPv6;
|
||||||
|
|
||||||
@@ -101,17 +120,21 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
|
|
||||||
setContentView(R.layout.profile_detail_view);
|
setContentView(R.layout.profile_detail_view);
|
||||||
|
|
||||||
mName = (EditText)findViewById(R.id.name);
|
mName = (MultiAutoCompleteTextView)findViewById(R.id.name);
|
||||||
|
mNameWrap = (TextInputLayoutHelper)findViewById(R.id.name_wrap);
|
||||||
mGateway = (EditText)findViewById(R.id.gateway);
|
mGateway = (EditText)findViewById(R.id.gateway);
|
||||||
|
mGatewayWrap = (TextInputLayoutHelper) findViewById(R.id.gateway_wrap);
|
||||||
mSelectVpnType = (Spinner)findViewById(R.id.vpn_type);
|
mSelectVpnType = (Spinner)findViewById(R.id.vpn_type);
|
||||||
mTncNotice = (RelativeLayout)findViewById(R.id.tnc_notice);
|
mTncNotice = (RelativeLayout)findViewById(R.id.tnc_notice);
|
||||||
|
|
||||||
mUsernamePassword = (ViewGroup)findViewById(R.id.username_password_group);
|
mUsernamePassword = (ViewGroup)findViewById(R.id.username_password_group);
|
||||||
mUsername = (EditText)findViewById(R.id.username);
|
mUsername = (EditText)findViewById(R.id.username);
|
||||||
|
mUsernameWrap = (TextInputLayoutHelper) findViewById(R.id.username_wrap);
|
||||||
mPassword = (EditText)findViewById(R.id.password);
|
mPassword = (EditText)findViewById(R.id.password);
|
||||||
|
|
||||||
mUserCertificate = (ViewGroup)findViewById(R.id.user_certificate_group);
|
mUserCertificate = (ViewGroup)findViewById(R.id.user_certificate_group);
|
||||||
mSelectUserCert = (RelativeLayout)findViewById(R.id.select_user_certificate);
|
mSelectUserCert = (RelativeLayout)findViewById(R.id.select_user_certificate);
|
||||||
|
mSelectUserId = (Spinner)findViewById(R.id.select_user_id);
|
||||||
|
|
||||||
mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
|
mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
|
||||||
mSelectCert = (RelativeLayout)findViewById(R.id.select_certificate);
|
mSelectCert = (RelativeLayout)findViewById(R.id.select_certificate);
|
||||||
@@ -119,11 +142,47 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
mShowAdvanced = (CheckBox)findViewById(R.id.show_advanced);
|
mShowAdvanced = (CheckBox)findViewById(R.id.show_advanced);
|
||||||
mAdvancedSettings = (ViewGroup)findViewById(R.id.advanced_settings);
|
mAdvancedSettings = (ViewGroup)findViewById(R.id.advanced_settings);
|
||||||
|
|
||||||
|
mRemoteId = (MultiAutoCompleteTextView)findViewById(R.id.remote_id);
|
||||||
|
mRemoteIdWrap = (TextInputLayoutHelper) findViewById(R.id.remote_id_wrap);
|
||||||
mMTU = (EditText)findViewById(R.id.mtu);
|
mMTU = (EditText)findViewById(R.id.mtu);
|
||||||
|
mMTUWrap = (TextInputLayoutHelper) findViewById(R.id.mtu_wrap);
|
||||||
mPort = (EditText)findViewById(R.id.port);
|
mPort = (EditText)findViewById(R.id.port);
|
||||||
|
mPortWrap = (TextInputLayoutHelper) findViewById(R.id.port_wrap);
|
||||||
mBlockIPv4 = (CheckBox)findViewById(R.id.split_tunneling_v4);
|
mBlockIPv4 = (CheckBox)findViewById(R.id.split_tunneling_v4);
|
||||||
mBlockIPv6 = (CheckBox)findViewById(R.id.split_tunneling_v6);
|
mBlockIPv6 = (CheckBox)findViewById(R.id.split_tunneling_v6);
|
||||||
|
|
||||||
|
final SpaceTokenizer spaceTokenizer = new SpaceTokenizer();
|
||||||
|
mName.setTokenizer(spaceTokenizer);
|
||||||
|
mRemoteId.setTokenizer(spaceTokenizer);
|
||||||
|
final ArrayAdapter<String> completeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line);
|
||||||
|
mName.setAdapter(completeAdapter);
|
||||||
|
mRemoteId.setAdapter(completeAdapter);
|
||||||
|
|
||||||
|
mGateway.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)
|
||||||
|
{
|
||||||
|
completeAdapter.clear();
|
||||||
|
completeAdapter.add(mGateway.getText().toString());
|
||||||
|
if (TextUtils.isEmpty(mGateway.getText()))
|
||||||
|
{
|
||||||
|
mNameWrap.setHelperText(getString(R.string.profile_name_hint));
|
||||||
|
mRemoteIdWrap.setHelperText(getString(R.string.profile_remote_id_hint));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNameWrap.setHelperText(String.format(getString(R.string.profile_name_hint_gateway), mGateway.getText()));
|
||||||
|
mRemoteIdWrap.setHelperText(String.format(getString(R.string.profile_remote_id_hint_gateway), mGateway.getText()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mSelectVpnType.setOnItemSelectedListener(new OnItemSelectedListener() {
|
mSelectVpnType.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
|
||||||
@@ -151,6 +210,24 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
});
|
});
|
||||||
|
|
||||||
mSelectUserCert.setOnClickListener(new SelectUserCertOnClickListener());
|
mSelectUserCert.setOnClickListener(new SelectUserCertOnClickListener());
|
||||||
|
mSelectUserIdAdapter = new CertificateIdentitiesAdapter(this);
|
||||||
|
mSelectUserId.setAdapter(mSelectUserIdAdapter);
|
||||||
|
mSelectUserId.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
|
||||||
|
{
|
||||||
|
if (mUserCertEntry != null)
|
||||||
|
{ /* we don't store the subject DN as it is in the reverse order and the default anyway */
|
||||||
|
mSelectedUserId = position == 0 ? null : mSelectUserIdAdapter.getItem(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent)
|
||||||
|
{
|
||||||
|
mSelectedUserId = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -211,6 +288,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
{
|
{
|
||||||
outState.putString(VpnProfileDataSource.KEY_USER_CERTIFICATE, mUserCertEntry.getAlias());
|
outState.putString(VpnProfileDataSource.KEY_USER_CERTIFICATE, mUserCertEntry.getAlias());
|
||||||
}
|
}
|
||||||
|
if (mSelectedUserId != null)
|
||||||
|
{
|
||||||
|
outState.putString(VpnProfileDataSource.KEY_LOCAL_ID, mSelectedUserId);
|
||||||
|
}
|
||||||
if (mCertEntry != null)
|
if (mCertEntry != null)
|
||||||
{
|
{
|
||||||
outState.putString(VpnProfileDataSource.KEY_CERTIFICATE, mCertEntry.getAlias());
|
outState.putString(VpnProfileDataSource.KEY_CERTIFICATE, mCertEntry.getAlias());
|
||||||
@@ -272,6 +353,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
|
|
||||||
if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
|
if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
|
||||||
{
|
{
|
||||||
|
mSelectUserId.setEnabled(false);
|
||||||
if (mUserCertLoading != null)
|
if (mUserCertLoading != null)
|
||||||
{
|
{
|
||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertLoading);
|
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertLoading);
|
||||||
@@ -282,11 +364,15 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setError(null);
|
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setError(null);
|
||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertEntry.getAlias());
|
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertEntry.getAlias());
|
||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(mUserCertEntry.getCertificate().getSubjectDN().toString());
|
((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(mUserCertEntry.getCertificate().getSubjectDN().toString());
|
||||||
|
mSelectUserIdAdapter.setCertificate(mUserCertEntry);
|
||||||
|
mSelectUserId.setSelection(mSelectUserIdAdapter.getPosition(mSelectedUserId));
|
||||||
|
mSelectUserId.setEnabled(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(R.string.profile_user_select_certificate_label);
|
((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(R.string.profile_user_select_certificate_label);
|
||||||
((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(R.string.profile_user_select_certificate);
|
((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(R.string.profile_user_select_certificate);
|
||||||
|
mSelectUserIdAdapter.setCertificate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +435,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
if (!show && mProfile != null)
|
if (!show && mProfile != null)
|
||||||
{
|
{
|
||||||
Integer st = mProfile.getSplitTunneling();
|
Integer st = mProfile.getSplitTunneling();
|
||||||
show = mProfile.getMTU() != null || mProfile.getPort() != null || (st != null && st != 0);
|
show = mProfile.getRemoteId() != null || mProfile.getMTU() != null ||
|
||||||
|
mProfile.getPort() != null || (st != null && st != 0);
|
||||||
}
|
}
|
||||||
mShowAdvanced.setVisibility(!show ? View.VISIBLE : View.GONE);
|
mShowAdvanced.setVisibility(!show ? View.VISIBLE : View.GONE);
|
||||||
mAdvancedSettings.setVisibility(show ? View.VISIBLE : View.GONE);
|
mAdvancedSettings.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
@@ -388,14 +475,14 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
if (mGateway.getText().toString().trim().isEmpty())
|
if (mGateway.getText().toString().trim().isEmpty())
|
||||||
{
|
{
|
||||||
mGateway.setError(getString(R.string.alert_text_no_input_gateway));
|
mGatewayWrap.setError(getString(R.string.alert_text_no_input_gateway));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
if (mVpnType.has(VpnTypeFeature.USER_PASS))
|
if (mVpnType.has(VpnTypeFeature.USER_PASS))
|
||||||
{
|
{
|
||||||
if (mUsername.getText().toString().trim().isEmpty())
|
if (mUsername.getText().toString().trim().isEmpty())
|
||||||
{
|
{
|
||||||
mUsername.setError(getString(R.string.alert_text_no_input_username));
|
mUsernameWrap.setError(getString(R.string.alert_text_no_input_username));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,13 +499,13 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
Integer mtu = getInteger(mMTU);
|
Integer mtu = getInteger(mMTU);
|
||||||
if (mtu != null && (mtu < MTU_MIN || mtu > MTU_MAX))
|
if (mtu != null && (mtu < MTU_MIN || mtu > MTU_MAX))
|
||||||
{
|
{
|
||||||
mMTU.setError(String.format(getString(R.string.alert_text_out_of_range), MTU_MIN, MTU_MAX));
|
mMTUWrap.setError(String.format(getString(R.string.alert_text_out_of_range), MTU_MIN, MTU_MAX));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
Integer port = getInteger(mPort);
|
Integer port = getInteger(mPort);
|
||||||
if (port != null && (port < 1 || port > 65535))
|
if (port != null && (port < 1 || port > 65535))
|
||||||
{
|
{
|
||||||
mPort.setError(String.format(getString(R.string.alert_text_out_of_range), 1, 65535));
|
mPortWrap.setError(String.format(getString(R.string.alert_text_out_of_range), 1, 65535));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
@@ -445,9 +532,12 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
|
if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
|
||||||
{
|
{
|
||||||
mProfile.setUserCertificateAlias(mUserCertEntry.getAlias());
|
mProfile.setUserCertificateAlias(mUserCertEntry.getAlias());
|
||||||
|
mProfile.setLocalId(mSelectedUserId);
|
||||||
}
|
}
|
||||||
String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias();
|
String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias();
|
||||||
mProfile.setCertificateAlias(certAlias);
|
mProfile.setCertificateAlias(certAlias);
|
||||||
|
String remote_id = mRemoteId.getText().toString().trim();
|
||||||
|
mProfile.setRemoteId(remote_id.isEmpty() ? null : remote_id);
|
||||||
mProfile.setMTU(getInteger(mMTU));
|
mProfile.setMTU(getInteger(mMTU));
|
||||||
mProfile.setPort(getInteger(mPort));
|
mProfile.setPort(getInteger(mPort));
|
||||||
int st = 0;
|
int st = 0;
|
||||||
@@ -463,7 +553,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
*/
|
*/
|
||||||
private void loadProfileData(Bundle savedInstanceState)
|
private void loadProfileData(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
String useralias = null, alias = null;
|
String useralias = null, local_id = null, alias = null;
|
||||||
|
|
||||||
getSupportActionBar().setTitle(R.string.add_profile);
|
getSupportActionBar().setTitle(R.string.add_profile);
|
||||||
if (mId != null && mId != 0)
|
if (mId != null && mId != 0)
|
||||||
@@ -476,11 +566,13 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
mVpnType = mProfile.getVpnType();
|
mVpnType = mProfile.getVpnType();
|
||||||
mUsername.setText(mProfile.getUsername());
|
mUsername.setText(mProfile.getUsername());
|
||||||
mPassword.setText(mProfile.getPassword());
|
mPassword.setText(mProfile.getPassword());
|
||||||
|
mRemoteId.setText(mProfile.getRemoteId());
|
||||||
mMTU.setText(mProfile.getMTU() != null ? mProfile.getMTU().toString() : null);
|
mMTU.setText(mProfile.getMTU() != null ? mProfile.getMTU().toString() : null);
|
||||||
mPort.setText(mProfile.getPort() != null ? mProfile.getPort().toString() : null);
|
mPort.setText(mProfile.getPort() != null ? mProfile.getPort().toString() : null);
|
||||||
mBlockIPv4.setChecked(mProfile.getSplitTunneling() != null ? (mProfile.getSplitTunneling() & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV4) != 0 : false);
|
mBlockIPv4.setChecked(mProfile.getSplitTunneling() != null ? (mProfile.getSplitTunneling() & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV4) != 0 : false);
|
||||||
mBlockIPv6.setChecked(mProfile.getSplitTunneling() != null ? (mProfile.getSplitTunneling() & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV6) != 0 : false);
|
mBlockIPv6.setChecked(mProfile.getSplitTunneling() != null ? (mProfile.getSplitTunneling() & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV6) != 0 : false);
|
||||||
useralias = mProfile.getUserCertificateAlias();
|
useralias = mProfile.getUserCertificateAlias();
|
||||||
|
local_id = mProfile.getLocalId();
|
||||||
alias = mProfile.getCertificateAlias();
|
alias = mProfile.getCertificateAlias();
|
||||||
getSupportActionBar().setTitle(mProfile.getName());
|
getSupportActionBar().setTitle(mProfile.getName());
|
||||||
}
|
}
|
||||||
@@ -495,11 +587,13 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
mSelectVpnType.setSelection(mVpnType.ordinal());
|
mSelectVpnType.setSelection(mVpnType.ordinal());
|
||||||
|
|
||||||
/* check if the user selected a user certificate previously */
|
/* check if the user selected a user certificate previously */
|
||||||
useralias = savedInstanceState == null ? useralias: savedInstanceState.getString(VpnProfileDataSource.KEY_USER_CERTIFICATE);
|
useralias = savedInstanceState == null ? useralias : savedInstanceState.getString(VpnProfileDataSource.KEY_USER_CERTIFICATE);
|
||||||
|
local_id = savedInstanceState == null ? local_id : savedInstanceState.getString(VpnProfileDataSource.KEY_LOCAL_ID);
|
||||||
if (useralias != null)
|
if (useralias != null)
|
||||||
{
|
{
|
||||||
UserCertificateLoader loader = new UserCertificateLoader(this, useralias);
|
UserCertificateLoader loader = new UserCertificateLoader(this, useralias);
|
||||||
mUserCertLoading = useralias;
|
mUserCertLoading = useralias;
|
||||||
|
mSelectedUserId = local_id;
|
||||||
loader.execute();
|
loader.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,4 +744,66 @@ public class VpnProfileDetailActivity extends AppCompatActivity
|
|||||||
}).create();
|
}).create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizer implementation that separates by white-space
|
||||||
|
*/
|
||||||
|
public static class SpaceTokenizer implements MultiAutoCompleteTextView.Tokenizer
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public int findTokenStart(CharSequence text, int cursor)
|
||||||
|
{
|
||||||
|
int i = cursor;
|
||||||
|
|
||||||
|
while (i > 0 && !Character.isWhitespace(text.charAt(i - 1)))
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int findTokenEnd(CharSequence text, int cursor)
|
||||||
|
{
|
||||||
|
int i = cursor;
|
||||||
|
int len = text.length();
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
if (Character.isWhitespace(text.charAt(i)))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence terminateToken(CharSequence text)
|
||||||
|
{
|
||||||
|
int i = text.length();
|
||||||
|
|
||||||
|
if (i > 0 && Character.isWhitespace(text.charAt(i - 1)))
|
||||||
|
{
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (text instanceof Spanned)
|
||||||
|
{
|
||||||
|
SpannableString sp = new SpannableString(text + " ");
|
||||||
|
TextUtils.copySpansFrom((Spanned) text, 0, text.length(), Object.class, sp, 0);
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return text + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -17,21 +17,12 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
|
||||||
import org.strongswan.android.data.VpnProfile;
|
|
||||||
import org.strongswan.android.data.VpnProfileDataSource;
|
|
||||||
import org.strongswan.android.ui.adapter.VpnProfileAdapter;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -46,6 +37,15 @@ import android.widget.AdapterView.OnItemClickListener;
|
|||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.data.VpnProfile;
|
||||||
|
import org.strongswan.android.data.VpnProfileDataSource;
|
||||||
|
import org.strongswan.android.ui.adapter.VpnProfileAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class VpnProfileListFragment extends Fragment
|
public class VpnProfileListFragment extends Fragment
|
||||||
{
|
{
|
||||||
private static final int ADD_REQUEST = 1;
|
private static final int ADD_REQUEST = 1;
|
||||||
@@ -66,10 +66,10 @@ public class VpnProfileListFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)
|
public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
super.onInflate(activity, attrs, savedInstanceState);
|
super.onInflate(context, attrs, savedInstanceState);
|
||||||
TypedArray a = activity.obtainStyledAttributes(attrs, R.styleable.Fragment);
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Fragment);
|
||||||
mReadOnly = a.getBoolean(R.styleable.Fragment_read_only, false);
|
mReadOnly = a.getBoolean(R.styleable.Fragment_read_only, false);
|
||||||
a.recycle();
|
a.recycle();
|
||||||
}
|
}
|
||||||
@@ -126,13 +126,13 @@ public class VpnProfileListFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity)
|
public void onAttach(Context context)
|
||||||
{
|
{
|
||||||
super.onAttach(activity);
|
super.onAttach(context);
|
||||||
|
|
||||||
if (activity instanceof OnVpnProfileSelectedListener)
|
if (context instanceof OnVpnProfileSelectedListener)
|
||||||
{
|
{
|
||||||
mListener = (OnVpnProfileSelectedListener)activity;
|
mListener = (OnVpnProfileSelectedListener)context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-74
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2013 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -27,6 +25,7 @@ import android.content.Intent;
|
|||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -34,6 +33,7 @@ import android.view.View;
|
|||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
import org.strongswan.android.R;
|
||||||
@@ -60,9 +60,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
private int mColorStateError;
|
private int mColorStateError;
|
||||||
private int mColorStateSuccess;
|
private int mColorStateSuccess;
|
||||||
private Button mActionButton;
|
private Button mActionButton;
|
||||||
private ProgressDialog mConnectDialog;
|
private ProgressBar mProgress;
|
||||||
private ProgressDialog mDisconnectDialog;
|
|
||||||
private ProgressDialog mProgressDialog;
|
|
||||||
private AlertDialog mErrorDialog;
|
private AlertDialog mErrorDialog;
|
||||||
private long mErrorConnectionID;
|
private long mErrorConnectionID;
|
||||||
private long mDismissedConnectionID;
|
private long mDismissedConnectionID;
|
||||||
@@ -133,8 +131,9 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
enableActionButton(false);
|
enableActionButton(null);
|
||||||
|
|
||||||
|
mProgress = (ProgressBar)view.findViewById(R.id.progress);
|
||||||
mStateView = (TextView)view.findViewById(R.id.vpn_state);
|
mStateView = (TextView)view.findViewById(R.id.vpn_state);
|
||||||
mColorStateBase = mStateView.getCurrentTextColor();
|
mColorStateBase = mStateView.getCurrentTextColor();
|
||||||
mProfileView = (TextView)view.findViewById(R.id.vpn_profile_label);
|
mProfileView = (TextView)view.findViewById(R.id.vpn_profile_label);
|
||||||
@@ -163,7 +162,6 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
mService.unregisterListener(this);
|
mService.unregisterListener(this);
|
||||||
}
|
}
|
||||||
hideErrorDialog();
|
hideErrorDialog();
|
||||||
hideProgressDialog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,33 +200,35 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enableActionButton(false);
|
|
||||||
mProfileNameView.setText(name);
|
mProfileNameView.setText(name);
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case DISABLED:
|
case DISABLED:
|
||||||
showProfile(false);
|
showProfile(false);
|
||||||
hideProgressDialog();
|
mProgress.setVisibility(View.GONE);
|
||||||
|
enableActionButton(null);
|
||||||
mStateView.setText(R.string.state_disabled);
|
mStateView.setText(R.string.state_disabled);
|
||||||
mStateView.setTextColor(mColorStateBase);
|
mStateView.setTextColor(mColorStateBase);
|
||||||
break;
|
break;
|
||||||
case CONNECTING:
|
case CONNECTING:
|
||||||
showProfile(true);
|
showProfile(true);
|
||||||
showConnectDialog(name, gateway);
|
mProgress.setVisibility(View.VISIBLE);
|
||||||
|
enableActionButton(getString(android.R.string.cancel));
|
||||||
mStateView.setText(R.string.state_connecting);
|
mStateView.setText(R.string.state_connecting);
|
||||||
mStateView.setTextColor(mColorStateBase);
|
mStateView.setTextColor(mColorStateBase);
|
||||||
break;
|
break;
|
||||||
case CONNECTED:
|
case CONNECTED:
|
||||||
showProfile(true);
|
showProfile(true);
|
||||||
hideProgressDialog();
|
mProgress.setVisibility(View.GONE);
|
||||||
enableActionButton(true);
|
enableActionButton(getString(R.string.disconnect));
|
||||||
mStateView.setText(R.string.state_connected);
|
mStateView.setText(R.string.state_connected);
|
||||||
mStateView.setTextColor(mColorStateSuccess);
|
mStateView.setTextColor(mColorStateSuccess);
|
||||||
break;
|
break;
|
||||||
case DISCONNECTING:
|
case DISCONNECTING:
|
||||||
showProfile(true);
|
showProfile(true);
|
||||||
showDisconnectDialog(name);
|
mProgress.setVisibility(View.VISIBLE);
|
||||||
|
enableActionButton(null);
|
||||||
mStateView.setText(R.string.state_disconnecting);
|
mStateView.setText(R.string.state_disconnecting);
|
||||||
mStateView.setTextColor(mColorStateBase);
|
mStateView.setTextColor(mColorStateBase);
|
||||||
break;
|
break;
|
||||||
@@ -254,10 +254,10 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
{ /* we already show the dialog */
|
{ /* we already show the dialog */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
hideProgressDialog();
|
|
||||||
mProfileNameView.setText(name);
|
mProfileNameView.setText(name);
|
||||||
showProfile(true);
|
showProfile(true);
|
||||||
enableActionButton(false);
|
mProgress.setVisibility(View.GONE);
|
||||||
|
enableActionButton(null);
|
||||||
mStateView.setText(R.string.state_error);
|
mStateView.setText(R.string.state_error);
|
||||||
mStateView.setTextColor(mColorStateError);
|
mStateView.setTextColor(mColorStateError);
|
||||||
switch (error)
|
switch (error)
|
||||||
@@ -294,20 +294,11 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
mProfileNameView.setVisibility(show ? View.VISIBLE : View.GONE);
|
mProfileNameView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableActionButton(boolean enable)
|
private void enableActionButton(String text)
|
||||||
{
|
{
|
||||||
mActionButton.setEnabled(enable);
|
mActionButton.setText(text);
|
||||||
mActionButton.setVisibility(enable ? View.VISIBLE : View.GONE);
|
mActionButton.setEnabled(text != null);
|
||||||
}
|
mActionButton.setVisibility(text != null ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
private void hideProgressDialog()
|
|
||||||
{
|
|
||||||
if (mProgressDialog != null)
|
|
||||||
{
|
|
||||||
mProgressDialog.dismiss();
|
|
||||||
mProgressDialog = null;
|
|
||||||
mDisconnectDialog = mConnectDialog = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hideErrorDialog()
|
private void hideErrorDialog()
|
||||||
@@ -329,50 +320,6 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
|||||||
updateView();
|
updateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showConnectDialog(String profile, String gateway)
|
|
||||||
{
|
|
||||||
if (mConnectDialog != null)
|
|
||||||
{ /* already showing the dialog */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hideProgressDialog();
|
|
||||||
mConnectDialog = new ProgressDialog(getActivity());
|
|
||||||
mConnectDialog.setTitle(String.format(getString(R.string.connecting_title), profile));
|
|
||||||
mConnectDialog.setMessage(String.format(getString(R.string.connecting_message), gateway));
|
|
||||||
mConnectDialog.setIndeterminate(true);
|
|
||||||
mConnectDialog.setCancelable(false);
|
|
||||||
mConnectDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
|
|
||||||
getString(android.R.string.cancel),
|
|
||||||
new DialogInterface.OnClickListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which)
|
|
||||||
{
|
|
||||||
if (mService != null)
|
|
||||||
{
|
|
||||||
mService.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mConnectDialog.show();
|
|
||||||
mProgressDialog = mConnectDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showDisconnectDialog(String profile)
|
|
||||||
{
|
|
||||||
if (mDisconnectDialog != null)
|
|
||||||
{ /* already showing the dialog */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hideProgressDialog();
|
|
||||||
mDisconnectDialog = new ProgressDialog(getActivity());
|
|
||||||
mDisconnectDialog.setMessage(getString(R.string.state_disconnecting));
|
|
||||||
mDisconnectDialog.setIndeterminate(true);
|
|
||||||
mDisconnectDialog.setCancelable(false);
|
|
||||||
mDisconnectDialog.show();
|
|
||||||
mProgressDialog = mDisconnectDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showErrorDialog(int textid)
|
private void showErrorDialog(int textid)
|
||||||
{
|
{
|
||||||
final List<RemediationInstruction> instructions = mService.getRemediationInstructions();
|
final List<RemediationInstruction> instructions = mService.getRemediationInstructions();
|
||||||
|
|||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Tobias Brunner
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.strongswan.android.ui.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.security.TrustedCertificateEntry;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CertificateIdentitiesAdapter extends ArrayAdapter<String>
|
||||||
|
{
|
||||||
|
TrustedCertificateEntry mCertificate;
|
||||||
|
|
||||||
|
public CertificateIdentitiesAdapter(Context context)
|
||||||
|
{
|
||||||
|
super(context, android.R.layout.simple_dropdown_item_1line);
|
||||||
|
extractIdentities();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new certificate for this adapter.
|
||||||
|
*
|
||||||
|
* @param certificate the certificate to extract identities from (null to clear)
|
||||||
|
*/
|
||||||
|
public void setCertificate(TrustedCertificateEntry certificate)
|
||||||
|
{
|
||||||
|
mCertificate = certificate;
|
||||||
|
clear();
|
||||||
|
extractIdentities();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractIdentities()
|
||||||
|
{
|
||||||
|
if (mCertificate == null)
|
||||||
|
{
|
||||||
|
add(getContext().getString(R.string.profile_user_select_id_init));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(String.format(getContext().getString(R.string.profile_user_select_id_default),
|
||||||
|
mCertificate.getCertificate().getSubjectDN().getName()));
|
||||||
|
addAll(mCertificate.getSubjectAltNames());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-3
@@ -63,12 +63,18 @@ public class VpnProfileAdapter extends ArrayAdapter<VpnProfile>
|
|||||||
TextView tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_name);
|
TextView tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_name);
|
||||||
tv.setText(profile.getName());
|
tv.setText(profile.getName());
|
||||||
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_gateway);
|
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_gateway);
|
||||||
tv.setText(getContext().getString(R.string.profile_gateway_label) + " " + profile.getGateway());
|
tv.setText(getContext().getString(R.string.profile_gateway_label) + ": " + profile.getGateway());
|
||||||
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_username);
|
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_username);
|
||||||
if (profile.getVpnType().has(VpnTypeFeature.USER_PASS))
|
if (profile.getVpnType().has(VpnTypeFeature.USER_PASS))
|
||||||
{ /* if the view is reused we make sure it is visible */
|
{ /* if the view is reused we make sure it is visible */
|
||||||
tv.setVisibility(View.VISIBLE);
|
tv.setVisibility(View.VISIBLE);
|
||||||
tv.setText(getContext().getString(R.string.profile_username_label) + " " + profile.getUsername());
|
tv.setText(getContext().getString(R.string.profile_username_label) + ": " + profile.getUsername());
|
||||||
|
}
|
||||||
|
else if (profile.getVpnType().has(VpnTypeFeature.CERTIFICATE) &&
|
||||||
|
profile.getLocalId() != null)
|
||||||
|
{
|
||||||
|
tv.setVisibility(View.VISIBLE);
|
||||||
|
tv.setText(getContext().getString(R.string.profile_user_select_id_label) + ": " + profile.getLocalId());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -77,7 +83,7 @@ public class VpnProfileAdapter extends ArrayAdapter<VpnProfile>
|
|||||||
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_certificate);
|
tv = (TextView)vpnProfileView.findViewById(R.id.profile_item_certificate);
|
||||||
if (profile.getVpnType().has(VpnTypeFeature.CERTIFICATE))
|
if (profile.getVpnType().has(VpnTypeFeature.CERTIFICATE))
|
||||||
{
|
{
|
||||||
tv.setText(getContext().getString(R.string.profile_user_certificate_label) + " " + profile.getUserCertificateAlias());
|
tv.setText(getContext().getString(R.string.profile_user_certificate_label) + ": " + profile.getUserCertificateAlias());
|
||||||
tv.setVisibility(View.VISIBLE);
|
tv.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+180
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Tobias Brunner
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.strongswan.android.ui.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.design.widget.TextInputLayout;
|
||||||
|
import android.support.v4.view.ViewCompat;
|
||||||
|
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.strongswan.android.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout that extends {@link android.support.design.widget.TextInputLayout} with a helper text
|
||||||
|
* displayed below the text field when it receives the focus. Also, any error message shown with
|
||||||
|
* {@link #setError(CharSequence)} is hidden when the text field is changed (this mirrors the
|
||||||
|
* behavior of {@link android.widget.EditText}).
|
||||||
|
*/
|
||||||
|
public class TextInputLayoutHelper extends TextInputLayout
|
||||||
|
{
|
||||||
|
private LinearLayout mHelperContainer;
|
||||||
|
private TextView mHelperText;
|
||||||
|
|
||||||
|
public TextInputLayoutHelper(Context context)
|
||||||
|
{
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextInputLayoutHelper(Context context, AttributeSet attrs)
|
||||||
|
{
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextInputLayoutHelper(Context context, AttributeSet attrs, int defStyleAttr)
|
||||||
|
{
|
||||||
|
super(context, attrs);
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextInputLayoutHelper);
|
||||||
|
String helper = a.getString(R.styleable.TextInputLayoutHelper_helper_text);
|
||||||
|
a.recycle();
|
||||||
|
if (helper != null)
|
||||||
|
{
|
||||||
|
mHelperContainer = new LinearLayout(context);
|
||||||
|
mHelperContainer.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
mHelperContainer.setVisibility(View.INVISIBLE);
|
||||||
|
addView(mHelperContainer, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
|
||||||
|
mHelperText = new TextView(context);
|
||||||
|
mHelperText.setText(helper);
|
||||||
|
mHelperText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
|
||||||
|
a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.textColorSecondary});
|
||||||
|
mHelperText.setTextColor(a.getColor(0, mHelperText.getCurrentTextColor()));
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
|
mHelperContainer.addView(mHelperText, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addView(View child, int index, ViewGroup.LayoutParams params)
|
||||||
|
{
|
||||||
|
super.addView(child, index, params);
|
||||||
|
if (child instanceof EditText)
|
||||||
|
{
|
||||||
|
EditText text = (EditText)child;
|
||||||
|
text.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)
|
||||||
|
{
|
||||||
|
if (getError() != null)
|
||||||
|
{
|
||||||
|
setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (mHelperContainer != null)
|
||||||
|
{
|
||||||
|
text.setOnFocusChangeListener(new OnFocusChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onFocusChange(View v, boolean hasFocus)
|
||||||
|
{
|
||||||
|
showHelper(hasFocus);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ViewCompat.setPaddingRelative(mHelperContainer, ViewCompat.getPaddingStart(text),
|
||||||
|
0, ViewCompat.getPaddingEnd(text), text.getPaddingBottom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(@Nullable CharSequence error)
|
||||||
|
{
|
||||||
|
super.setError(error);
|
||||||
|
if (mHelperContainer != null)
|
||||||
|
{
|
||||||
|
if (error == null)
|
||||||
|
{ /* this frees up space used by the now invisible error message */
|
||||||
|
setErrorEnabled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* re-add the helper as the error message should be displayed directly under the textbox */
|
||||||
|
removeView(mHelperContainer);
|
||||||
|
addView(mHelperContainer, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the helper text to be displayed below the text field.
|
||||||
|
*
|
||||||
|
* @attr ref R.styleable#TextInputLayoutHelper_helper_text
|
||||||
|
*/
|
||||||
|
public void setHelperText(CharSequence text)
|
||||||
|
{
|
||||||
|
mHelperText.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showHelper(boolean show)
|
||||||
|
{
|
||||||
|
if (show == (mHelperContainer.getVisibility() == View.VISIBLE))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (show)
|
||||||
|
{
|
||||||
|
ViewCompat.animate(mHelperContainer)
|
||||||
|
.alpha(1f)
|
||||||
|
.setDuration(200)
|
||||||
|
.setListener(new ViewPropertyAnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(View view)
|
||||||
|
{
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ViewCompat.animate(mHelperContainer)
|
||||||
|
.alpha(0f)
|
||||||
|
.setDuration(200)
|
||||||
|
.setListener(new ViewPropertyAnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(View view)
|
||||||
|
{
|
||||||
|
view.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,14 @@ endif
|
|||||||
strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) \
|
strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) \
|
||||||
$(strongswan_BYOD_PLUGINS)
|
$(strongswan_BYOD_PLUGINS)
|
||||||
|
|
||||||
include $(LOCAL_PATH)/strongswan/Android.common.mk
|
strongswan_DIR := ../../../../../../../
|
||||||
|
|
||||||
# includes
|
# includes
|
||||||
strongswan_PATH := $(LOCAL_PATH)/strongswan
|
strongswan_PATH := $(LOCAL_PATH)/$(strongswan_DIR)
|
||||||
openssl_PATH := $(LOCAL_PATH)/openssl/include
|
openssl_PATH := $(LOCAL_PATH)/openssl/include
|
||||||
|
|
||||||
|
include $(strongswan_PATH)/Android.common.mk
|
||||||
|
|
||||||
# CFLAGS (partially from a configure run using droid-gcc)
|
# CFLAGS (partially from a configure run using droid-gcc)
|
||||||
strongswan_CFLAGS := \
|
strongswan_CFLAGS := \
|
||||||
-Wall \
|
-Wall \
|
||||||
@@ -67,15 +69,15 @@ endif
|
|||||||
strongswan_BUILD := \
|
strongswan_BUILD := \
|
||||||
openssl \
|
openssl \
|
||||||
libandroidbridge \
|
libandroidbridge \
|
||||||
strongswan/src/libipsec \
|
$(strongswan_DIR)/src/libipsec \
|
||||||
strongswan/src/libcharon \
|
$(strongswan_DIR)/src/libcharon \
|
||||||
strongswan/src/libstrongswan
|
$(strongswan_DIR)/src/libstrongswan
|
||||||
|
|
||||||
ifneq ($(strongswan_USE_BYOD),)
|
ifneq ($(strongswan_USE_BYOD),)
|
||||||
strongswan_BUILD += \
|
strongswan_BUILD += \
|
||||||
strongswan/src/libtnccs \
|
$(strongswan_DIR)/src/libtnccs \
|
||||||
strongswan/src/libtncif \
|
$(strongswan_DIR)/src/libtncif \
|
||||||
strongswan/src/libimcv
|
$(strongswan_DIR)/src/libimcv
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
|
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
|
||||||
|
|||||||
+129
-82
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2015 Tobias Brunner
|
* Copyright (C) 2010-2016 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -430,6 +430,84 @@ CALLBACK(reestablish, job_requeue_t,
|
|||||||
return JOB_REQUEUE_NONE;
|
return JOB_REQUEUE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(listener_t, ike_updown, bool,
|
||||||
|
private_android_service_t *this, ike_sa_t *ike_sa, bool up)
|
||||||
|
{
|
||||||
|
/* this callback is only registered during initiation, so if the IKE_SA
|
||||||
|
* goes down we assume some kind of authentication error, more specific
|
||||||
|
* errors are catched in the alert() handler */
|
||||||
|
if (this->ike_sa == ike_sa && !up)
|
||||||
|
{
|
||||||
|
charonservice->update_status(charonservice,
|
||||||
|
CHARONSERVICE_AUTH_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(listener_t, ike_rekey, bool,
|
||||||
|
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
|
||||||
|
{
|
||||||
|
if (this->ike_sa == old)
|
||||||
|
{
|
||||||
|
this->ike_sa = new;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(listener_t, ike_reestablish_post_redirect, bool,
|
||||||
|
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new,
|
||||||
|
bool initiated)
|
||||||
|
{
|
||||||
|
if (this->ike_sa == old && initiated)
|
||||||
|
{ /* if we get redirected during IKE_AUTH we just migrate to the new SA,
|
||||||
|
* we don't have a TUN device yet, so reinstalling it without DNS would
|
||||||
|
* fail (and using the DNS proxy is not required anyway) */
|
||||||
|
this->ike_sa = new;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(listener_t, ike_reestablish_pre, bool,
|
||||||
|
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
|
||||||
|
{
|
||||||
|
if (this->ike_sa == old)
|
||||||
|
{
|
||||||
|
/* enable DNS proxy so hosts are properly resolved while the TUN device
|
||||||
|
* is still active */
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
this->use_dns_proxy = TRUE;
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
/* if DNS servers are installed that are only reachable through the VPN
|
||||||
|
* the DNS proxy doesn't help, so uninstall DNS servers */
|
||||||
|
if (!setup_tun_device_without_dns(this))
|
||||||
|
{
|
||||||
|
DBG1(DBG_DMN, "failed to setup TUN device without DNS");
|
||||||
|
charonservice->update_status(charonservice,
|
||||||
|
CHARONSERVICE_GENERIC_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(listener_t, ike_reestablish_post, bool,
|
||||||
|
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new,
|
||||||
|
bool initiated)
|
||||||
|
{
|
||||||
|
if (this->ike_sa == old && initiated)
|
||||||
|
{
|
||||||
|
this->ike_sa = new;
|
||||||
|
/* re-register hook to detect initiation failures */
|
||||||
|
this->public.listener.ike_updown = _ike_updown;
|
||||||
|
/* if the IKE_SA got deleted by the responder we get the child_down()
|
||||||
|
* event on the old IKE_SA after this hook has been called, so they
|
||||||
|
* get ignored and thus we trigger the event here */
|
||||||
|
charonservice->update_status(charonservice,
|
||||||
|
CHARONSERVICE_CHILD_STATE_DOWN);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(listener_t, child_updown, bool,
|
METHOD(listener_t, child_updown, bool,
|
||||||
private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
||||||
bool up)
|
bool up)
|
||||||
@@ -440,6 +518,9 @@ METHOD(listener_t, child_updown, bool,
|
|||||||
{
|
{
|
||||||
/* disable the hooks registered to catch initiation failures */
|
/* disable the hooks registered to catch initiation failures */
|
||||||
this->public.listener.ike_updown = NULL;
|
this->public.listener.ike_updown = NULL;
|
||||||
|
/* enable hooks to handle reauthentications */
|
||||||
|
this->public.listener.ike_reestablish_pre = _ike_reestablish_pre;
|
||||||
|
this->public.listener.ike_reestablish_post = _ike_reestablish_post;
|
||||||
/* CHILD_SA is up so we can disable the DNS proxy we enabled to
|
/* CHILD_SA is up so we can disable the DNS proxy we enabled to
|
||||||
* reestablish the SA */
|
* reestablish the SA */
|
||||||
this->lock->write_lock(this->lock);
|
this->lock->write_lock(this->lock);
|
||||||
@@ -465,21 +546,6 @@ METHOD(listener_t, child_updown, bool,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(listener_t, ike_updown, bool,
|
|
||||||
private_android_service_t *this, ike_sa_t *ike_sa, bool up)
|
|
||||||
{
|
|
||||||
/* this callback is only registered during initiation, so if the IKE_SA
|
|
||||||
* goes down we assume some kind of authentication error, more specific
|
|
||||||
* errors are catched in the alert() handler */
|
|
||||||
if (this->ike_sa == ike_sa && !up)
|
|
||||||
{
|
|
||||||
charonservice->update_status(charonservice,
|
|
||||||
CHARONSERVICE_AUTH_ERROR);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(listener_t, alert, bool,
|
METHOD(listener_t, alert, bool,
|
||||||
private_android_service_t *this, ike_sa_t *ike_sa, alert_t alert,
|
private_android_service_t *this, ike_sa_t *ike_sa, alert_t alert,
|
||||||
va_list args)
|
va_list args)
|
||||||
@@ -554,62 +620,12 @@ METHOD(listener_t, alert, bool,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(listener_t, ike_rekey, bool,
|
|
||||||
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
|
|
||||||
{
|
|
||||||
if (this->ike_sa == old)
|
|
||||||
{
|
|
||||||
this->ike_sa = new;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(listener_t, ike_reestablish_pre, bool,
|
|
||||||
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
|
|
||||||
{
|
|
||||||
if (this->ike_sa == old)
|
|
||||||
{
|
|
||||||
/* enable DNS proxy so hosts are properly resolved while the TUN device
|
|
||||||
* is still active */
|
|
||||||
this->lock->write_lock(this->lock);
|
|
||||||
this->use_dns_proxy = TRUE;
|
|
||||||
this->lock->unlock(this->lock);
|
|
||||||
/* if DNS servers are installed that are only reachable through the VPN
|
|
||||||
* the DNS proxy doesn't help, so uninstall DNS servers */
|
|
||||||
if (!setup_tun_device_without_dns(this))
|
|
||||||
{
|
|
||||||
DBG1(DBG_DMN, "failed to setup TUN device without DNS");
|
|
||||||
charonservice->update_status(charonservice,
|
|
||||||
CHARONSERVICE_GENERIC_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(listener_t, ike_reestablish_post, bool,
|
|
||||||
private_android_service_t *this, ike_sa_t *old, ike_sa_t *new,
|
|
||||||
bool initiated)
|
|
||||||
{
|
|
||||||
if (this->ike_sa == old && initiated)
|
|
||||||
{
|
|
||||||
this->ike_sa = new;
|
|
||||||
/* re-register hook to detect initiation failures */
|
|
||||||
this->public.listener.ike_updown = _ike_updown;
|
|
||||||
/* if the IKE_SA got deleted by the responder we get the child_down()
|
|
||||||
* event on the old IKE_SA after this hook has been called, so they
|
|
||||||
* get ignored and thus we trigger the event here */
|
|
||||||
charonservice->update_status(charonservice,
|
|
||||||
CHARONSERVICE_CHILD_STATE_DOWN);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_auth_cfg_pw(private_android_service_t *this,
|
static void add_auth_cfg_pw(private_android_service_t *this,
|
||||||
peer_cfg_t *peer_cfg, bool byod)
|
peer_cfg_t *peer_cfg, bool byod)
|
||||||
{
|
{
|
||||||
identification_t *user;
|
identification_t *user, *id = NULL;
|
||||||
auth_cfg_t *auth;
|
auth_cfg_t *auth;
|
||||||
char *username, *password;
|
char *username, *password, *local_id;
|
||||||
|
|
||||||
auth = auth_cfg_create();
|
auth = auth_cfg_create();
|
||||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
|
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
|
||||||
@@ -622,8 +638,19 @@ static void add_auth_cfg_pw(private_android_service_t *this,
|
|||||||
NULL);
|
NULL);
|
||||||
password = this->settings->get_str(this->settings, "connection.password",
|
password = this->settings->get_str(this->settings, "connection.password",
|
||||||
NULL);
|
NULL);
|
||||||
|
local_id = this->settings->get_str(this->settings, "connection.local_id",
|
||||||
|
NULL);
|
||||||
user = identification_create_from_string(username);
|
user = identification_create_from_string(username);
|
||||||
auth->add(auth, AUTH_RULE_IDENTITY, user);
|
auth->add(auth, AUTH_RULE_EAP_IDENTITY, user);
|
||||||
|
if (local_id)
|
||||||
|
{
|
||||||
|
id = identification_create_from_string(local_id);
|
||||||
|
}
|
||||||
|
if (!id)
|
||||||
|
{
|
||||||
|
id = user->clone(user);
|
||||||
|
}
|
||||||
|
auth->add(auth, AUTH_RULE_IDENTITY, id);
|
||||||
|
|
||||||
this->creds->add_username_password(this->creds, username, password);
|
this->creds->add_username_password(this->creds, username, password);
|
||||||
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
|
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
|
||||||
@@ -633,9 +660,9 @@ static bool add_auth_cfg_cert(private_android_service_t *this,
|
|||||||
peer_cfg_t *peer_cfg)
|
peer_cfg_t *peer_cfg)
|
||||||
{
|
{
|
||||||
certificate_t *cert;
|
certificate_t *cert;
|
||||||
identification_t *id;
|
identification_t *id = NULL;
|
||||||
auth_cfg_t *auth;
|
auth_cfg_t *auth;
|
||||||
char *type;
|
char *type, *local_id;
|
||||||
|
|
||||||
cert = this->creds->load_user_certificate(this->creds);
|
cert = this->creds->load_user_certificate(this->creds);
|
||||||
if (!cert)
|
if (!cert)
|
||||||
@@ -649,8 +676,8 @@ static bool add_auth_cfg_cert(private_android_service_t *this,
|
|||||||
{
|
{
|
||||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
|
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
|
||||||
auth->add(auth, AUTH_RULE_EAP_TYPE, EAP_TLS);
|
auth->add(auth, AUTH_RULE_EAP_TYPE, EAP_TLS);
|
||||||
id = identification_create_from_string("%any");
|
auth->add(auth, AUTH_RULE_AAA_IDENTITY,
|
||||||
auth->add(auth, AUTH_RULE_AAA_IDENTITY, id);
|
identification_create_from_string("%any"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -658,15 +685,25 @@ static bool add_auth_cfg_cert(private_android_service_t *this,
|
|||||||
}
|
}
|
||||||
auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
|
auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
|
||||||
|
|
||||||
id = cert->get_subject(cert);
|
local_id = this->settings->get_str(this->settings, "connection.local_id",
|
||||||
auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
|
NULL);
|
||||||
|
if (local_id)
|
||||||
|
{
|
||||||
|
id = identification_create_from_string(local_id);
|
||||||
|
}
|
||||||
|
if (!id)
|
||||||
|
{
|
||||||
|
id = cert->get_subject(cert);
|
||||||
|
id = id->clone(id);
|
||||||
|
}
|
||||||
|
auth->add(auth, AUTH_RULE_IDENTITY, id);
|
||||||
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
|
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static job_requeue_t initiate(private_android_service_t *this)
|
static job_requeue_t initiate(private_android_service_t *this)
|
||||||
{
|
{
|
||||||
identification_t *gateway;
|
identification_t *gateway = NULL;
|
||||||
ike_cfg_t *ike_cfg;
|
ike_cfg_t *ike_cfg;
|
||||||
peer_cfg_t *peer_cfg;
|
peer_cfg_t *peer_cfg;
|
||||||
child_cfg_t *child_cfg;
|
child_cfg_t *child_cfg;
|
||||||
@@ -692,7 +729,7 @@ static job_requeue_t initiate(private_android_service_t *this)
|
|||||||
.dpd_action = ACTION_RESTART,
|
.dpd_action = ACTION_RESTART,
|
||||||
.close_action = ACTION_RESTART,
|
.close_action = ACTION_RESTART,
|
||||||
};
|
};
|
||||||
char *type, *server;
|
char *type, *server, *remote_id;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
server = this->settings->get_str(this->settings, "connection.server", NULL);
|
server = this->settings->get_str(this->settings, "connection.server", NULL);
|
||||||
@@ -731,9 +768,20 @@ static job_requeue_t initiate(private_android_service_t *this)
|
|||||||
|
|
||||||
/* remote auth config */
|
/* remote auth config */
|
||||||
auth = auth_cfg_create();
|
auth = auth_cfg_create();
|
||||||
gateway = identification_create_from_string(server);
|
remote_id = this->settings->get_str(this->settings, "connection.remote_id",
|
||||||
|
NULL);
|
||||||
|
if (remote_id)
|
||||||
|
{
|
||||||
|
gateway = identification_create_from_string(remote_id);
|
||||||
|
}
|
||||||
|
if (!gateway || gateway->get_type(gateway) == ID_ANY)
|
||||||
|
{
|
||||||
|
DESTROY_IF(gateway);
|
||||||
|
gateway = identification_create_from_string(server);
|
||||||
|
/* only use this if remote ID was not configured explicitly */
|
||||||
|
auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, TRUE);
|
||||||
|
}
|
||||||
auth->add(auth, AUTH_RULE_IDENTITY, gateway);
|
auth->add(auth, AUTH_RULE_IDENTITY, gateway);
|
||||||
auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, TRUE);
|
|
||||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||||
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
|
||||||
|
|
||||||
@@ -824,8 +872,7 @@ android_service_t *android_service_create(android_creds_t *creds,
|
|||||||
.public = {
|
.public = {
|
||||||
.listener = {
|
.listener = {
|
||||||
.ike_rekey = _ike_rekey,
|
.ike_rekey = _ike_rekey,
|
||||||
.ike_reestablish_pre = _ike_reestablish_pre,
|
.ike_reestablish_post = _ike_reestablish_post_redirect,
|
||||||
.ike_reestablish_post = _ike_reestablish_post,
|
|
||||||
.ike_updown = _ike_updown,
|
.ike_updown = _ike_updown,
|
||||||
.child_updown = _child_updown,
|
.child_updown = _child_updown,
|
||||||
.alert = _alert,
|
.alert = _alert,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#define ANDROID_RETRASNMIT_TRIES 3
|
#define ANDROID_RETRASNMIT_TRIES 3
|
||||||
#define ANDROID_RETRANSMIT_TIMEOUT 2.0
|
#define ANDROID_RETRANSMIT_TIMEOUT 2.0
|
||||||
#define ANDROID_RETRANSMIT_BASE 1.4
|
#define ANDROID_RETRANSMIT_BASE 1.4
|
||||||
|
#define ANDROID_KEEPALIVE_INTERVAL 45
|
||||||
|
|
||||||
typedef struct private_charonservice_t private_charonservice_t;
|
typedef struct private_charonservice_t private_charonservice_t;
|
||||||
|
|
||||||
@@ -466,6 +467,9 @@ static void set_options(char *logfile)
|
|||||||
"charon.retransmit_timeout", ANDROID_RETRANSMIT_TIMEOUT);
|
"charon.retransmit_timeout", ANDROID_RETRANSMIT_TIMEOUT);
|
||||||
lib->settings->set_double(lib->settings,
|
lib->settings->set_double(lib->settings,
|
||||||
"charon.retransmit_base", ANDROID_RETRANSMIT_BASE);
|
"charon.retransmit_base", ANDROID_RETRANSMIT_BASE);
|
||||||
|
/* increase NAT-T keepalive interval a bit to save battery power */
|
||||||
|
lib->settings->set_time(lib->settings,
|
||||||
|
"charon.keep_alive", ANDROID_KEEPALIVE_INTERVAL);
|
||||||
lib->settings->set_bool(lib->settings,
|
lib->settings->set_bool(lib->settings,
|
||||||
"charon.initiator_only", TRUE);
|
"charon.initiator_only", TRUE);
|
||||||
lib->settings->set_bool(lib->settings,
|
lib->settings->set_bool(lib->settings,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2012 Tobias Brunner
|
Copyright (C) 2012-2016 Tobias Brunner
|
||||||
Copyright (C) 2012 Giuliano Grassi
|
Copyright (C) 2012 Giuliano Grassi
|
||||||
Copyright (C) 2012 Ralf Sager
|
Copyright (C) 2012 Ralf Sager
|
||||||
Hochschule fuer Technik Rapperswil
|
HSR Hochschule fuer Technik Rapperswil
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
@@ -15,37 +15,41 @@
|
|||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
for more details.
|
for more details.
|
||||||
-->
|
-->
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="5dp"
|
android:padding="10dp" >
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<TextView
|
<android.support.design.widget.TextInputLayout
|
||||||
android:layout_height="wrap_content"
|
android:id="@+id/username_wrap"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:text="@string/profile_username_label"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/username"
|
android:layout_height="wrap_content" >
|
||||||
android:enabled="false"
|
|
||||||
android:inputType="none" />
|
|
||||||
|
|
||||||
<TextView
|
<android.support.design.widget.TextInputEditText
|
||||||
android:layout_height="wrap_content"
|
android:id="@+id/username"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:text="@string/profile_password_label"
|
android:layout_height="wrap_content"
|
||||||
android:textStyle="bold" />
|
android:enabled="false"
|
||||||
|
android:inputType="none"
|
||||||
|
android:hint="@string/profile_username_label" />
|
||||||
|
|
||||||
<EditText
|
</android.support.design.widget.TextInputLayout>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
|
<android.support.design.widget.TextInputLayout
|
||||||
|
android:id="@+id/password_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/password"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textPassword|textNoSuggestions"
|
android:layout_marginTop="4dp" >
|
||||||
android:singleLine="true" />
|
|
||||||
|
<android.support.design.widget.TextInputEditText
|
||||||
|
android:id="@+id/password"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="textPassword|textNoSuggestions"
|
||||||
|
android:hint="@string/profile_password_label" />
|
||||||
|
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2012-2015 Tobias Brunner
|
Copyright (C) 2012-2016 Tobias Brunner
|
||||||
Copyright (C) 2012 Giuliano Grassi
|
Copyright (C) 2012 Giuliano Grassi
|
||||||
Copyright (C) 2012 Ralf Sager
|
Copyright (C) 2012 Ralf Sager
|
||||||
Hochschule fuer Technik Rapperswil
|
HSR Hochschule fuer Technik Rapperswil
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
@@ -16,46 +16,39 @@
|
|||||||
for more details.
|
for more details.
|
||||||
-->
|
-->
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="match_parent" >
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dp" >
|
android:padding="10dp"
|
||||||
|
android:animateLayoutChanges="true" >
|
||||||
|
|
||||||
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
|
android:id="@+id/gateway_wrap"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
app:helper_text="@string/profile_gateway_hint" >
|
||||||
|
|
||||||
|
<android.support.design.widget.TextInputEditText
|
||||||
|
android:id="@+id/gateway"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="textNoSuggestions"
|
||||||
|
android:hint="@string/profile_gateway_label" />
|
||||||
|
|
||||||
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginLeft="4dp"
|
||||||
android:text="@string/profile_name_label" />
|
android:textSize="12sp"
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/name"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:inputType="textNoSuggestions"
|
|
||||||
android:hint="@string/profile_name_hint" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/profile_gateway_label" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/gateway"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:inputType="textNoSuggestions" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/profile_vpn_type_label" />
|
android:text="@string/profile_vpn_type_label" />
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
@@ -76,32 +69,37 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
|
|
||||||
<TextView
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
|
android:id="@+id/username_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" >
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/profile_username_label" />
|
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/username"
|
android:id="@+id/username"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:inputType="textNoSuggestions" />
|
android:inputType="textNoSuggestions"
|
||||||
|
android:hint="@string/profile_username_label" />
|
||||||
|
|
||||||
<TextView
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/profile_password_label" />
|
|
||||||
|
|
||||||
<EditText
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
android:id="@+id/password"
|
android:id="@+id/password_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:layout_marginTop="4dp"
|
||||||
android:inputType="textPassword|textNoSuggestions"
|
app:helper_text="@string/profile_password_hint" >
|
||||||
android:hint="@string/profile_password_hint" />
|
|
||||||
|
<android.support.design.widget.TextInputEditText
|
||||||
|
android:id="@+id/password"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="textPassword|textNoSuggestions"
|
||||||
|
android:hint="@string/profile_password_label" />
|
||||||
|
|
||||||
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -109,36 +107,73 @@
|
|||||||
android:id="@+id/user_certificate_group"
|
android:id="@+id/user_certificate_group"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:textSize="12sp"
|
||||||
android:text="@string/profile_user_certificate_label" />
|
android:text="@string/profile_user_certificate_label" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/select_user_certificate"
|
android:id="@+id/select_user_certificate"
|
||||||
layout="@layout/two_line_button" />
|
layout="@layout/two_line_button" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:text="@string/profile_user_select_id_label" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/select_user_id"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:spinnerMode="dropdown" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginLeft="4dp"
|
||||||
|
android:textSize="12sp"
|
||||||
android:text="@string/profile_ca_label" />
|
android:text="@string/profile_ca_label" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/ca_auto"
|
android:id="@+id/ca_auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
android:text="@string/profile_ca_auto_label" />
|
android:text="@string/profile_ca_auto_label" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/select_certificate"
|
android:id="@+id/select_certificate"
|
||||||
layout="@layout/two_line_button" />
|
layout="@layout/two_line_button" />
|
||||||
|
|
||||||
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
|
android:id="@+id/name_wrap"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:helper_text="@string/profile_name_hint" >
|
||||||
|
|
||||||
|
<MultiAutoCompleteTextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="textNoSuggestions"
|
||||||
|
android:completionThreshold="1"
|
||||||
|
android:hint="@string/profile_name_label" />
|
||||||
|
|
||||||
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/show_advanced"
|
android:id="@+id/show_advanced"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -155,34 +190,66 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/profile_mtu_label" />
|
android:layout_marginLeft="4dp"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:text="@string/profile_advanced_label" />
|
||||||
|
|
||||||
<EditText
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
android:id="@+id/mtu"
|
android:id="@+id/remote_id_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:layout_marginTop="10dp"
|
||||||
android:inputType="number|textNoSuggestions"
|
app:helper_text="@string/profile_remote_id_hint" >
|
||||||
android:hint="@string/profile_use_default_hint" />
|
|
||||||
|
<MultiAutoCompleteTextView
|
||||||
|
android:id="@+id/remote_id"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="textNoSuggestions"
|
||||||
|
android:completionThreshold="1"
|
||||||
|
android:hint="@string/profile_remote_id_label" />
|
||||||
|
|
||||||
<TextView
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
|
android:id="@+id/mtu_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
app:helper_text="@string/profile_mtu_hint" >
|
||||||
android:text="@string/profile_port_label" />
|
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/port"
|
android:id="@+id/mtu"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="number|textNoSuggestions"
|
||||||
|
android:hint="@string/profile_mtu_label" />
|
||||||
|
|
||||||
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
|
<org.strongswan.android.ui.widget.TextInputLayoutHelper
|
||||||
|
android:id="@+id/port_wrap"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
app:helper_text="@string/profile_port_hint" >
|
||||||
android:inputType="number|textNoSuggestions"
|
|
||||||
android:hint="@string/profile_use_default_hint" />
|
<android.support.design.widget.TextInputEditText
|
||||||
|
android:id="@+id/port"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="number|textNoSuggestions"
|
||||||
|
android:hint="@string/profile_port_label" />
|
||||||
|
|
||||||
|
</org.strongswan.android.ui.widget.TextInputLayoutHelper>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:textSize="12sp"
|
||||||
android:text="@string/profile_split_tunneling_label" />
|
android:text="@string/profile_split_tunneling_label" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
@@ -198,6 +265,7 @@
|
|||||||
android:text="@string/profile_split_tunnelingv6_title" />
|
android:text="@string/profile_split_tunnelingv6_title" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2013 Tobias Brunner
|
Copyright (C) 2013-2016 Tobias Brunner
|
||||||
Hochschule fuer Technik Rapperswil
|
Hochschule fuer Technik Rapperswil
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<include
|
<FrameLayout
|
||||||
layout="@android:layout/list_content"
|
android:id="@+id/list_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
for more details.
|
for more details.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:strongswan="http://schemas.android.com/apk/res/org.strongswan.android"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
@@ -25,6 +25,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
strongswan:read_only="true" />
|
app:read_only="true" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2012-2013 Tobias Brunner
|
Copyright (C) 2012-2016 Tobias Brunner
|
||||||
Copyright (C) 2012 Giuliano Grassi
|
Copyright (C) 2012 Giuliano Grassi
|
||||||
Copyright (C) 2012 Ralf Sager
|
Copyright (C) 2012 Ralf Sager
|
||||||
Hochschule fuer Technik Rapperswil
|
Hochschule fuer Technik Rapperswil
|
||||||
@@ -72,6 +72,17 @@
|
|||||||
</TextView>
|
</TextView>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/action"
|
android:id="@+id/action"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -49,30 +49,40 @@
|
|||||||
<!-- VPN profile details -->
|
<!-- VPN profile details -->
|
||||||
<string name="profile_edit_save">Speichern</string>
|
<string name="profile_edit_save">Speichern</string>
|
||||||
<string name="profile_edit_cancel">Abbrechen</string>
|
<string name="profile_edit_cancel">Abbrechen</string>
|
||||||
<string name="profile_name_label">Profilname:</string>
|
<string name="profile_name_label">Profilname (optional)</string>
|
||||||
<string name="profile_name_hint">(Server-Adresse verwenden)</string>
|
<string name="profile_name_hint">Standardwert ist der konfigurierte Server</string>
|
||||||
<string name="profile_gateway_label">Server:</string>
|
<string name="profile_name_hint_gateway">Standardwert ist \"%1$s\"</string>
|
||||||
<string name="profile_vpn_type_label">Typ:</string>
|
<string name="profile_gateway_label">Server</string>
|
||||||
<string name="profile_username_label">Benutzername:</string>
|
<string name="profile_gateway_hint">IP-Adresse oder Hostname des VPN Servers</string>
|
||||||
<string name="profile_password_label">Passwort:</string>
|
<string name="profile_vpn_type_label">VPN-Typ</string>
|
||||||
<string name="profile_password_hint">(anfordern wenn benötigt)</string>
|
<string name="profile_username_label">Benutzername</string>
|
||||||
<string name="profile_user_certificate_label">Benutzer-Zertifikat:</string>
|
<string name="profile_password_label">Passwort (optional)</string>
|
||||||
|
<string name="profile_password_hint">Leer lassen, um bei Bedarf danach gefragt zu werden</string>
|
||||||
|
<string name="profile_user_certificate_label">Benutzer-Zertifikat</string>
|
||||||
<string name="profile_user_select_certificate_label">Benutzer-Zertifikat auswählen</string>
|
<string name="profile_user_select_certificate_label">Benutzer-Zertifikat auswählen</string>
|
||||||
<string name="profile_user_select_certificate">Wählen Sie ein bestimmtes Benutzer-Zertifikat</string>
|
<string name="profile_user_select_certificate">Wählen Sie ein bestimmtes Benutzer-Zertifikat</string>
|
||||||
<string name="profile_ca_label">CA-Zertifikat:</string>
|
<string name="profile_user_select_id_label">Benutzer-Identität</string>
|
||||||
|
<string name="profile_user_select_id_init">Wählen Sie zuerst ein Benutzer-Zertifikat</string>
|
||||||
|
<string name="profile_user_select_id_default">Standardwert (%1$s)</string>
|
||||||
|
<string name="profile_ca_label">CA-Zertifikat</string>
|
||||||
<string name="profile_ca_auto_label">Automatisch wählen</string>
|
<string name="profile_ca_auto_label">Automatisch wählen</string>
|
||||||
<string name="profile_ca_select_certificate_label">CA-Zertifikat auswählen</string>
|
<string name="profile_ca_select_certificate_label">CA-Zertifikat auswählen</string>
|
||||||
<string name="profile_ca_select_certificate">Wählen Sie ein bestimmtes CA-Zertifikat</string>
|
<string name="profile_ca_select_certificate">Wählen Sie ein bestimmtes CA-Zertifikat</string>
|
||||||
|
<string name="profile_advanced_label">Erweiterte Einstellungen</string>
|
||||||
<string name="profile_show_advanced_label">Erweiterte Einstellungen anzeigen</string>
|
<string name="profile_show_advanced_label">Erweiterte Einstellungen anzeigen</string>
|
||||||
<string name="profile_mtu_label">MTU:</string>
|
<string name="profile_remote_id_label">Server-Identität</string>
|
||||||
<string name="profile_port_label">Server Port:</string>
|
<string name="profile_remote_id_hint">Standardwert ist der konfigurierte Server. Eigene Werte werden explizit and den Server gesendet und während der Authentifizierung erzwungen</string>
|
||||||
<string name="profile_use_default_hint">(Standardwert verwenden)</string>
|
<string name="profile_remote_id_hint_gateway">Standardwert ist \"%1$s\". Eigene Werte werden explizit and den Server gesendet und während der Authentifizierung erzwungen</string>
|
||||||
<string name="profile_split_tunneling_label">Split-Tunneling:</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>
|
||||||
|
<string name="profile_port_hint">UDP-Port zu dem verbunden wird, falls dieser vom Standard-Port abweicht</string>
|
||||||
|
<string name="profile_split_tunneling_label">Split-Tunneling</string>
|
||||||
<string name="profile_split_tunnelingv4_title">Blockiere IPv4 Verkehr der nicht für das VPN bestimmt ist</string>
|
<string name="profile_split_tunnelingv4_title">Blockiere IPv4 Verkehr der nicht für das VPN bestimmt ist</string>
|
||||||
<string name="profile_split_tunnelingv6_title">Blockiere IPv6 Verkehr der nicht für das VPN bestimmt ist</string>
|
<string name="profile_split_tunnelingv6_title">Blockiere IPv6 Verkehr der nicht für das VPN bestimmt ist</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Bitte geben Sie hier die Server-Adresse ein</string>
|
<string name="alert_text_no_input_gateway">Ein Wert wird benötigt, um die Verbindung aufbauen zu können</string>
|
||||||
<string name="alert_text_no_input_username">Bitte geben Sie hier Ihren Benutzernamen ein</string>
|
<string name="alert_text_no_input_username">Bitte geben Sie Ihren Benutzernamen ein</string>
|
||||||
<string name="alert_text_nocertfound_title">Kein CA-Zertifikat ausgewählt</string>
|
<string name="alert_text_nocertfound_title">Kein CA-Zertifikat ausgewählt</string>
|
||||||
<string name="alert_text_nocertfound">Bitte wählen Sie eines aus oder aktivieren Sie <i>Automatisch wählen</i></string>
|
<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_out_of_range">Bitte geben Sie eine Nummer von %1$d - %2$d ein</string>
|
||||||
@@ -122,8 +132,6 @@
|
|||||||
<string name="error_auth_failed">Benutzerauthentifizierung ist fehlgeschlagen.</string>
|
<string name="error_auth_failed">Benutzerauthentifizierung ist fehlgeschlagen.</string>
|
||||||
<string name="error_assessment_failed">Sicherheitsassessment ist fehlgeschlagen.</string>
|
<string name="error_assessment_failed">Sicherheitsassessment ist fehlgeschlagen.</string>
|
||||||
<string name="error_generic">Unbekannter Fehler während des Verbindens.</string>
|
<string name="error_generic">Unbekannter Fehler während des Verbindens.</string>
|
||||||
<string name="connecting_title">Verbinden: %1$s</string>
|
|
||||||
<string name="connecting_message">Verbinde mit \""%1$s\".</string>
|
|
||||||
<string name="vpn_connected">VPN verbunden</string>
|
<string name="vpn_connected">VPN verbunden</string>
|
||||||
<string name="vpn_profile_connected">Dieses VPN Profil ist momentan verbunden!</string>
|
<string name="vpn_profile_connected">Dieses VPN Profil ist momentan verbunden!</string>
|
||||||
<string name="reconnect">Neu verbinden</string>
|
<string name="reconnect">Neu verbinden</string>
|
||||||
|
|||||||
@@ -49,36 +49,46 @@
|
|||||||
<!-- VPN profile details -->
|
<!-- VPN profile details -->
|
||||||
<string name="profile_edit_save">Zapisz</string>
|
<string name="profile_edit_save">Zapisz</string>
|
||||||
<string name="profile_edit_cancel">Anuluj</string>
|
<string name="profile_edit_cancel">Anuluj</string>
|
||||||
<string name="profile_name_label">Nazwa profilu:</string>
|
<string name="profile_name_label">Nazwa profilu (opcjonalny)</string>
|
||||||
<string name="profile_name_hint">(użyj adresu serwer)</string>
|
<string name="profile_name_hint">Defaults to the configured server</string>
|
||||||
<string name="profile_gateway_label">Serwer:</string>
|
<string name="profile_name_hint_gateway">Defaults to \"%1$s\"</string>
|
||||||
<string name="profile_vpn_type_label">Typ:</string>
|
<string name="profile_gateway_label">Serwer</string>
|
||||||
<string name="profile_username_label">Użytkownik:</string>
|
<string name="profile_gateway_hint">IP address or hostname of the VPN server</string>
|
||||||
<string name="profile_password_label">Hasło:</string>
|
<string name="profile_vpn_type_label">Typ VPN</string>
|
||||||
<string name="profile_password_hint">(w razie potrzeby zapromptuj)</string>
|
<string name="profile_username_label">Użytkownik</string>
|
||||||
<string name="profile_user_certificate_label">Certyfikat użytkownika:</string>
|
<string name="profile_password_label">Hasło (opcjonalny)</string>
|
||||||
|
<string name="profile_password_hint">Leave blank to get prompted on demand</string>
|
||||||
|
<string name="profile_user_certificate_label">Certyfikat użytkownika</string>
|
||||||
<string name="profile_user_select_certificate_label">Wybierz certyfikat użytkownika</string>
|
<string name="profile_user_select_certificate_label">Wybierz certyfikat użytkownika</string>
|
||||||
<string name="profile_user_select_certificate">>Wybierz określony certyfikat użytkownika</string>
|
<string name="profile_user_select_certificate">>Wybierz określony certyfikat użytkownika</string>
|
||||||
<string name="profile_ca_label">Certyfikat CA:</string>
|
<string name="profile_user_select_id_label">User identity</string>
|
||||||
|
<string name="profile_user_select_id_init">Select a certificate first</string>
|
||||||
|
<string name="profile_user_select_id_default">Default (%1$s)</string>
|
||||||
|
<string name="profile_ca_label">Certyfikat CA</string>
|
||||||
<string name="profile_ca_auto_label">Wybierz automatycznie</string>
|
<string name="profile_ca_auto_label">Wybierz automatycznie</string>
|
||||||
<string name="profile_ca_select_certificate_label">Wybierz certyfikat CA</string>
|
<string name="profile_ca_select_certificate_label">Wybierz certyfikat CA</string>
|
||||||
<string name="profile_ca_select_certificate">Wybierz określony certyfikat CA</string>
|
<string name="profile_ca_select_certificate">Wybierz określony certyfikat CA</string>
|
||||||
|
<string name="profile_advanced_label">Advanced settings</string>
|
||||||
<string name="profile_show_advanced_label">Show advanced settings</string>
|
<string name="profile_show_advanced_label">Show advanced settings</string>
|
||||||
<string name="profile_mtu_label">MTU:</string>
|
<string name="profile_remote_id_label">Server identity</string>
|
||||||
<string name="profile_port_label">Server port:</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_use_default_hint">(use default)</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_split_tunneling_label">Split tunneling:</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>
|
||||||
|
<string name="profile_port_hint">UDP port to connect to, if different from the default</string>
|
||||||
|
<string name="profile_split_tunneling_label">Split tunneling</string>
|
||||||
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
||||||
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Wprowadź adres serwer</string>
|
<string name="alert_text_no_input_gateway">A value is required to initiate the connection</string>
|
||||||
<string name="alert_text_no_input_username">Wprowadź swoją nazwę użytkownika</string>
|
<string name="alert_text_no_input_username">Wprowadź swoją nazwę użytkownika</string>
|
||||||
<string name="alert_text_nocertfound_title">Nie wybrano żadnego certyfikatu CA</string>
|
<string name="alert_text_nocertfound_title">Nie wybrano żadnego certyfikatu CA</string>
|
||||||
<string name="alert_text_nocertfound">Wybierz lub uaktywnij jeden <i>Wybierz automatycznie</i></string>
|
<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_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
|
||||||
<string name="tnc_notice_title">EAP-TNC may affect your privacy</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>
|
<string name="tnc_notice_subtitle">Device data is sent to the server operator</string>
|
||||||
<string name="tnc_notice_details"><p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b></string>
|
<string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>]]></string>
|
||||||
|
|
||||||
<!-- Trusted certificate selection -->
|
<!-- Trusted certificate selection -->
|
||||||
<string name="trusted_certs_title">Certyfikaty CA</string>
|
<string name="trusted_certs_title">Certyfikaty CA</string>
|
||||||
@@ -122,8 +132,6 @@
|
|||||||
<string name="error_auth_failed">Błąd przy autoryzacji użytkownika</string>
|
<string name="error_auth_failed">Błąd przy autoryzacji użytkownika</string>
|
||||||
<string name="error_assessment_failed">Security assessment failed.</string>
|
<string name="error_assessment_failed">Security assessment failed.</string>
|
||||||
<string name="error_generic">Nieznany błąd w czasie połączenia</string>
|
<string name="error_generic">Nieznany błąd w czasie połączenia</string>
|
||||||
<string name="connecting_title">Łączenie: %1$s</string>
|
|
||||||
<string name="connecting_message">Tworzenie tunelu VPN z \""%1$s\".</string>
|
|
||||||
<string name="vpn_connected">Połączenie z VPN</string>
|
<string name="vpn_connected">Połączenie z VPN</string>
|
||||||
<string name="vpn_profile_connected">Ten profil VPN jest obecnie połaczony!</string>
|
<string name="vpn_profile_connected">Ten profil VPN jest obecnie połaczony!</string>
|
||||||
<string name="reconnect">Połączyć ponownie</string>
|
<string name="reconnect">Połączyć ponownie</string>
|
||||||
|
|||||||
@@ -46,29 +46,39 @@
|
|||||||
<!-- VPN profile details -->
|
<!-- VPN profile details -->
|
||||||
<string name="profile_edit_save">Сохранить</string>
|
<string name="profile_edit_save">Сохранить</string>
|
||||||
<string name="profile_edit_cancel">Отмена</string>
|
<string name="profile_edit_cancel">Отмена</string>
|
||||||
<string name="profile_name_label">Название профиля:</string>
|
<string name="profile_name_label">Название профиля (необязательный)</string>
|
||||||
<string name="profile_name_hint">(адрес cервер)</string>
|
<string name="profile_name_hint">Defaults to the configured server</string>
|
||||||
<string name="profile_gateway_label">Сервер:</string>
|
<string name="profile_name_hint_gateway">Defaults to \"%1$s\"</string>
|
||||||
<string name="profile_vpn_type_label">Тип:</string>
|
<string name="profile_gateway_label">Сервер</string>
|
||||||
<string name="profile_username_label">Логин:</string>
|
<string name="profile_gateway_hint">IP address or hostname of the VPN server</string>
|
||||||
<string name="profile_password_label">Пароль:</string>
|
<string name="profile_vpn_type_label">VPN Тип</string>
|
||||||
<string name="profile_password_hint">(спросить если нужно)</string>
|
<string name="profile_username_label">Логин</string>
|
||||||
<string name="profile_user_certificate_label">Сертификат пользователя:</string>
|
<string name="profile_password_label">Пароль (необязательный)</string>
|
||||||
|
<string name="profile_password_hint">Leave blank to get prompted on demand</string>
|
||||||
|
<string name="profile_user_certificate_label">Сертификат пользователя</string>
|
||||||
<string name="profile_user_select_certificate_label">Выбрать сертификат пользователя</string>
|
<string name="profile_user_select_certificate_label">Выбрать сертификат пользователя</string>
|
||||||
<string name="profile_user_select_certificate">Выбрать сертификат пользователя</string>
|
<string name="profile_user_select_certificate">Выбрать сертификат пользователя</string>
|
||||||
<string name="profile_ca_label">Сертификат CA:</string>
|
<string name="profile_user_select_id_label">User identity</string>
|
||||||
|
<string name="profile_user_select_id_init">Select a certificate first</string>
|
||||||
|
<string name="profile_user_select_id_default">Default (%1$s)</string>
|
||||||
|
<string name="profile_ca_label">Сертификат CA</string>
|
||||||
<string name="profile_ca_auto_label">Выбрать автоматически</string>
|
<string name="profile_ca_auto_label">Выбрать автоматически</string>
|
||||||
<string name="profile_ca_select_certificate_label">Выбрать сертификат CA</string>
|
<string name="profile_ca_select_certificate_label">Выбрать сертификат CA</string>
|
||||||
<string name="profile_ca_select_certificate">Выбрать CA сертификат</string>
|
<string name="profile_ca_select_certificate">Выбрать CA сертификат</string>
|
||||||
|
<string name="profile_advanced_label">Advanced settings</string>
|
||||||
<string name="profile_show_advanced_label">Show advanced settings</string>
|
<string name="profile_show_advanced_label">Show advanced settings</string>
|
||||||
<string name="profile_mtu_label">MTU:</string>
|
<string name="profile_remote_id_label">Server identity</string>
|
||||||
<string name="profile_port_label">Server port:</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_use_default_hint">(use default)</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_split_tunneling_label">Split tunneling:</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>
|
||||||
|
<string name="profile_port_hint">UDP port to connect to, if different from the default</string>
|
||||||
|
<string name="profile_split_tunneling_label">Split tunneling</string>
|
||||||
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
||||||
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Пожалуйста введите адрес cервер</string>
|
<string name="alert_text_no_input_gateway">A value is required to initiate the connection</string>
|
||||||
<string name="alert_text_no_input_username">Пожалуйста введите имя пользователя</string>
|
<string name="alert_text_no_input_username">Пожалуйста введите имя пользователя</string>
|
||||||
<string name="alert_text_nocertfound_title">Не выбран сертификат CA</string>
|
<string name="alert_text_nocertfound_title">Не выбран сертификат CA</string>
|
||||||
<string name="alert_text_nocertfound">Пожалуйста выберите один <i>Выбрать автоматически</i></string>
|
<string name="alert_text_nocertfound">Пожалуйста выберите один <i>Выбрать автоматически</i></string>
|
||||||
@@ -119,8 +129,6 @@
|
|||||||
<string name="error_auth_failed">Ошибка авторизации пользователя.</string>
|
<string name="error_auth_failed">Ошибка авторизации пользователя.</string>
|
||||||
<string name="error_assessment_failed">Security assessment failed.</string>
|
<string name="error_assessment_failed">Security assessment failed.</string>
|
||||||
<string name="error_generic">Неизвестная ошибка.</string>
|
<string name="error_generic">Неизвестная ошибка.</string>
|
||||||
<string name="connecting_title">Подключение: %1$s</string>
|
|
||||||
<string name="connecting_message">Подключение к VPN с \""%1$s\".</string>
|
|
||||||
<string name="vpn_connected">Соединение с VPN установлено</string>
|
<string name="vpn_connected">Соединение с VPN установлено</string>
|
||||||
<string name="vpn_profile_connected">Подключение к этому профилю VPN уже существует!</string>
|
<string name="vpn_profile_connected">Подключение к этому профилю VPN уже существует!</string>
|
||||||
<string name="reconnect">Переподключить</string>
|
<string name="reconnect">Переподключить</string>
|
||||||
@@ -129,4 +137,3 @@
|
|||||||
<string name="connect">Соединить</string>
|
<string name="connect">Соединить</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -47,30 +47,40 @@
|
|||||||
<!-- VPN profile details -->
|
<!-- VPN profile details -->
|
||||||
<string name="profile_edit_save">Зберегти</string>
|
<string name="profile_edit_save">Зберегти</string>
|
||||||
<string name="profile_edit_cancel">Відміна</string>
|
<string name="profile_edit_cancel">Відміна</string>
|
||||||
<string name="profile_name_label">Назва профілю:</string>
|
<string name="profile_name_label">Назва профілю (необов\'язковий)</string>
|
||||||
<string name="profile_name_hint">(використовувати адресу cервер)</string>
|
<string name="profile_name_hint">Defaults to the configured server</string>
|
||||||
<string name="profile_gateway_label">Сервер:</string>
|
<string name="profile_name_hint_gateway">Defaults to \"%1$s\"</string>
|
||||||
<string name="profile_vpn_type_label">Тип:</string>
|
<string name="profile_gateway_label">Сервер</string>
|
||||||
<string name="profile_username_label">Логін:</string>
|
<string name="profile_gateway_hint">IP address or hostname of the VPN server</string>
|
||||||
<string name="profile_password_label">Пароль:</string>
|
<string name="profile_vpn_type_label">VPN Тип</string>
|
||||||
<string name="profile_password_hint">(запитати якщо потрібно)</string>
|
<string name="profile_username_label">Логін</string>
|
||||||
<string name="profile_user_certificate_label">Сертифікат користувача:</string>
|
<string name="profile_password_label">Пароль (необов\'язковий)</string>
|
||||||
|
<string name="profile_password_hint">Leave blank to get prompted on demand</string>
|
||||||
|
<string name="profile_user_certificate_label">Сертифікат користувача</string>
|
||||||
<string name="profile_user_select_certificate_label">Виберіть сертифікат користувача</string>
|
<string name="profile_user_select_certificate_label">Виберіть сертифікат користувача</string>
|
||||||
<string name="profile_user_select_certificate">Вибрати спеціальний сертифікат користувача</string>
|
<string name="profile_user_select_certificate">Вибрати спеціальний сертифікат користувача</string>
|
||||||
<string name="profile_ca_label">Сертифікат CA:</string>
|
<string name="profile_user_select_id_label">User identity</string>
|
||||||
|
<string name="profile_user_select_id_init">Select a certificate first</string>
|
||||||
|
<string name="profile_user_select_id_default">Default (%1$s)</string>
|
||||||
|
<string name="profile_ca_label">Сертифікат CA</string>
|
||||||
<string name="profile_ca_auto_label">Вибрати автоматично</string>
|
<string name="profile_ca_auto_label">Вибрати автоматично</string>
|
||||||
<string name="profile_ca_select_certificate_label">Вибрати сертифікат CA</string>
|
<string name="profile_ca_select_certificate_label">Вибрати сертифікат CA</string>
|
||||||
<string name="profile_ca_select_certificate">Вибрати спеціальний сертифікат CA</string>
|
<string name="profile_ca_select_certificate">Вибрати спеціальний сертифікат CA</string>
|
||||||
|
<string name="profile_advanced_label">Advanced settings</string>
|
||||||
<string name="profile_show_advanced_label">Show advanced settings</string>
|
<string name="profile_show_advanced_label">Show advanced settings</string>
|
||||||
<string name="profile_mtu_label">MTU:</string>
|
<string name="profile_remote_id_label">Server identity</string>
|
||||||
<string name="profile_port_label">Server port:</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_use_default_hint">(use default)</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_split_tunneling_label">Split tunneling:</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>
|
||||||
|
<string name="profile_port_hint">UDP port to connect to, if different from the default</string>
|
||||||
|
<string name="profile_split_tunneling_label">Split tunneling</string>
|
||||||
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
||||||
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Введіть адресу cервер тут</string>
|
<string name="alert_text_no_input_gateway">A value is required to initiate the connection</string>
|
||||||
<string name="alert_text_no_input_username">Введіть ім\'я користувача тут</string>
|
<string name="alert_text_no_input_username">Введіть ім\'я користувача </string>
|
||||||
<string name="alert_text_nocertfound_title">Не вибрано сертифікат CA</string>
|
<string name="alert_text_nocertfound_title">Не вибрано сертифікат CA</string>
|
||||||
<string name="alert_text_nocertfound">Будь ласка виберіть один <i>Вибрати автоматично</i></string>
|
<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_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
|
||||||
@@ -120,8 +130,6 @@
|
|||||||
<string name="error_auth_failed">Помилка аутентифікації користувача.</string>
|
<string name="error_auth_failed">Помилка аутентифікації користувача.</string>
|
||||||
<string name="error_assessment_failed">Security assessment failed.</string>
|
<string name="error_assessment_failed">Security assessment failed.</string>
|
||||||
<string name="error_generic">Невідома помилка під час підключення.</string>
|
<string name="error_generic">Невідома помилка під час підключення.</string>
|
||||||
<string name="connecting_title">Підключення: %1$s</string>
|
|
||||||
<string name="connecting_message">Підключення VPN з \""%1$s\".</string>
|
|
||||||
<string name="vpn_connected">VPN підключено</string>
|
<string name="vpn_connected">VPN підключено</string>
|
||||||
<string name="vpn_profile_connected">Цей VPN профіль зараз підключений!</string>
|
<string name="vpn_profile_connected">Цей VPN профіль зараз підключений!</string>
|
||||||
<string name="reconnect">Перепідключитися</string>
|
<string name="reconnect">Перепідключитися</string>
|
||||||
@@ -130,4 +138,3 @@
|
|||||||
<string name="connect">Підключити</string>
|
<string name="connect">Підключити</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2012 Tobias Brunner
|
Copyright (C) 2012-2016 Tobias Brunner
|
||||||
Hochschule fuer Technik Rapperswil
|
HSR Hochschule fuer Technik Rapperswil
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
@@ -17,4 +17,7 @@
|
|||||||
<declare-styleable name="Fragment">
|
<declare-styleable name="Fragment">
|
||||||
<attr name="read_only" format="boolean" />
|
<attr name="read_only" format="boolean" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
<declare-styleable name="TextInputLayoutHelper">
|
||||||
|
<attr name="helper_text" format="string" />
|
||||||
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -49,30 +49,40 @@
|
|||||||
<!-- VPN profile details -->
|
<!-- VPN profile details -->
|
||||||
<string name="profile_edit_save">Save</string>
|
<string name="profile_edit_save">Save</string>
|
||||||
<string name="profile_edit_cancel">Cancel</string>
|
<string name="profile_edit_cancel">Cancel</string>
|
||||||
<string name="profile_name_label">Profile Name:</string>
|
<string name="profile_name_label">Profile name (optional)</string>
|
||||||
<string name="profile_name_hint">(use server address)</string>
|
<string name="profile_name_hint">Defaults to the configured server</string>
|
||||||
<string name="profile_gateway_label">Server:</string>
|
<string name="profile_name_hint_gateway">Defaults to \"%1$s\"</string>
|
||||||
<string name="profile_vpn_type_label">Type:</string>
|
<string name="profile_gateway_label">Server</string>
|
||||||
<string name="profile_username_label">Username:</string>
|
<string name="profile_gateway_hint">IP address or hostname of the VPN server</string>
|
||||||
<string name="profile_password_label">Password:</string>
|
<string name="profile_vpn_type_label">VPN Type</string>
|
||||||
<string name="profile_password_hint">(prompt when needed)</string>
|
<string name="profile_username_label">Username</string>
|
||||||
<string name="profile_user_certificate_label">User certificate:</string>
|
<string name="profile_password_label">Password (optional)</string>
|
||||||
|
<string name="profile_password_hint">Leave blank to get prompted on demand</string>
|
||||||
|
<string name="profile_user_certificate_label">User certificate</string>
|
||||||
<string name="profile_user_select_certificate_label">Select user certificate</string>
|
<string name="profile_user_select_certificate_label">Select user certificate</string>
|
||||||
<string name="profile_user_select_certificate">Select a specific user certificate</string>
|
<string name="profile_user_select_certificate">Select a specific user certificate</string>
|
||||||
<string name="profile_ca_label">CA certificate:</string>
|
<string name="profile_user_select_id_label">User identity</string>
|
||||||
|
<string name="profile_user_select_id_init">Select a certificate first</string>
|
||||||
|
<string name="profile_user_select_id_default">Default (%1$s)</string>
|
||||||
|
<string name="profile_ca_label">CA certificate</string>
|
||||||
<string name="profile_ca_auto_label">Select automatically</string>
|
<string name="profile_ca_auto_label">Select automatically</string>
|
||||||
<string name="profile_ca_select_certificate_label">Select CA certificate</string>
|
<string name="profile_ca_select_certificate_label">Select CA certificate</string>
|
||||||
<string name="profile_ca_select_certificate">Select a specific CA certificate</string>
|
<string name="profile_ca_select_certificate">Select a specific CA certificate</string>
|
||||||
|
<string name="profile_advanced_label">Advanced settings</string>
|
||||||
<string name="profile_show_advanced_label">Show advanced settings</string>
|
<string name="profile_show_advanced_label">Show advanced settings</string>
|
||||||
<string name="profile_mtu_label">MTU:</string>
|
<string name="profile_remote_id_label">Server identity</string>
|
||||||
<string name="profile_port_label">Server port:</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_use_default_hint">(use default)</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_split_tunneling_label">Split tunneling:</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>
|
||||||
|
<string name="profile_port_hint">UDP port to connect to, if different from the default</string>
|
||||||
|
<string name="profile_split_tunneling_label">Split tunneling</string>
|
||||||
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv4_title">Block IPv4 traffic not destined for the VPN</string>
|
||||||
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
<string name="profile_split_tunnelingv6_title">Block IPv6 traffic not destined for the VPN</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Please enter the server address here</string>
|
<string name="alert_text_no_input_gateway">A value is required to initiate the connection</string>
|
||||||
<string name="alert_text_no_input_username">Please enter your username here</string>
|
<string name="alert_text_no_input_username">Please enter your username </string>
|
||||||
<string name="alert_text_nocertfound_title">No CA certificate selected</string>
|
<string name="alert_text_nocertfound_title">No CA certificate selected</string>
|
||||||
<string name="alert_text_nocertfound">Please select one or activate <i>Select automatically</i></string>
|
<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_out_of_range">Please enter a number in the range from %1$d - %2$d</string>
|
||||||
@@ -122,8 +132,6 @@
|
|||||||
<string name="error_auth_failed">User authentication failed.</string>
|
<string name="error_auth_failed">User authentication failed.</string>
|
||||||
<string name="error_assessment_failed">Security assessment failed.</string>
|
<string name="error_assessment_failed">Security assessment failed.</string>
|
||||||
<string name="error_generic">Unspecified failure while connecting.</string>
|
<string name="error_generic">Unspecified failure while connecting.</string>
|
||||||
<string name="connecting_title">Connecting: %1$s</string>
|
|
||||||
<string name="connecting_message">Establishing VPN with \""%1$s\".</string>
|
|
||||||
<string name="vpn_connected">VPN connected</string>
|
<string name="vpn_connected">VPN connected</string>
|
||||||
<string name="vpn_profile_connected">This VPN profile is currently connected!</string>
|
<string name="vpn_profile_connected">This VPN profile is currently connected!</string>
|
||||||
<string name="reconnect">Reconnect</string>
|
<string name="reconnect">Reconnect</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user