From fb919a72262b43ffa3d93239afa6fb1621341f28 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 22 Aug 2017 21:48:42 -0500 Subject: [PATCH] Use data binding to provide EditText input filters Signed-off-by: Jason A. Donenfeld --- .../wireguard/android/BindingAdapters.java | 9 +++- .../wireguard/android/ConfigEditFragment.java | 15 ------ .../com/wireguard/android/KeyInputFilter.java | 7 ++- .../wireguard/android/NameInputFilter.java | 46 +++++++++++++++++++ .../java/com/wireguard/config/Config.java | 3 +- .../main/res/layout/config_edit_fragment.xml | 13 ++++-- 6 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/wireguard/android/NameInputFilter.java diff --git a/app/src/main/java/com/wireguard/android/BindingAdapters.java b/app/src/main/java/com/wireguard/android/BindingAdapters.java index 6f375fe2..ec465930 100644 --- a/app/src/main/java/com/wireguard/android/BindingAdapters.java +++ b/app/src/main/java/com/wireguard/android/BindingAdapters.java @@ -4,7 +4,7 @@ import android.databinding.BindingAdapter; import android.databinding.ObservableArrayMap; import android.databinding.ObservableList; import android.graphics.Typeface; -import android.widget.EditText; +import android.text.InputFilter; import android.widget.ListView; import android.widget.TextView; @@ -62,8 +62,13 @@ public final class BindingAdapters { } } + @BindingAdapter({"filter"}) + public static void setFilter(final TextView view, final InputFilter filter) { + view.setFilters(new InputFilter[]{filter}); + } + @BindingAdapter({"android:textStyle"}) - public static void textStyleBinding(final TextView view, final Typeface typeface) { + public static void setTextStyle(final TextView view, final Typeface typeface) { view.setTypeface(typeface); } diff --git a/app/src/main/java/com/wireguard/android/ConfigEditFragment.java b/app/src/main/java/com/wireguard/android/ConfigEditFragment.java index 384aadef..dab5097f 100644 --- a/app/src/main/java/com/wireguard/android/ConfigEditFragment.java +++ b/app/src/main/java/com/wireguard/android/ConfigEditFragment.java @@ -2,8 +2,6 @@ package com.wireguard.android; import android.content.Context; import android.os.Bundle; -import android.text.InputFilter; -import android.text.LoginFilter; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -11,7 +9,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; import android.widget.Toast; import com.wireguard.android.databinding.ConfigEditFragmentBinding; @@ -45,18 +42,6 @@ public class ConfigEditFragment extends BaseConfigFragment { final Bundle savedInstanceState) { final ConfigEditFragmentBinding binding = ConfigEditFragmentBinding.inflate(inflater, parent, false); - final EditText configNameText = binding.getRoot().findViewById(R.id.config_name_text); - configNameText.setFilters(new InputFilter[]{ - new InputFilter.LengthFilter(16), - new LoginFilter.UsernameFilterGeneric() { - @Override - public boolean isAllowed(final char c) { - return Character.isLetterOrDigit(c) || "_=+.-".indexOf(c) != -1; - } - } - }); - final EditText privateKeyText = binding.getRoot().findViewById(R.id.private_key_text); - privateKeyText.setFilters(new InputFilter[]{new KeyInputFilter()}); binding.setConfig(localConfig); return binding.getRoot(); } diff --git a/app/src/main/java/com/wireguard/android/KeyInputFilter.java b/app/src/main/java/com/wireguard/android/KeyInputFilter.java index 758528c9..d8eabd6c 100644 --- a/app/src/main/java/com/wireguard/android/KeyInputFilter.java +++ b/app/src/main/java/com/wireguard/android/KeyInputFilter.java @@ -9,7 +9,12 @@ import com.wireguard.crypto.KeyEncoding; /** * InputFilter for entering WireGuard private/public keys encoded with base64. */ -class KeyInputFilter implements InputFilter { + +public class KeyInputFilter implements InputFilter { + public static KeyInputFilter newInstance() { + return new KeyInputFilter(); + } + @Override public CharSequence filter(final CharSequence source, final int sStart, final int sEnd, diff --git a/app/src/main/java/com/wireguard/android/NameInputFilter.java b/app/src/main/java/com/wireguard/android/NameInputFilter.java new file mode 100644 index 00000000..cd653c11 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/NameInputFilter.java @@ -0,0 +1,46 @@ +package com.wireguard.android; + +import android.text.InputFilter; +import android.text.SpannableStringBuilder; +import android.text.Spanned; + +import com.wireguard.config.Config; + +/** + * InputFilter for entering WireGuard configuration names (Linux interface names). + */ + +public class NameInputFilter implements InputFilter { + public static NameInputFilter newInstance() { + return new NameInputFilter(); + } + + @Override + public CharSequence filter(final CharSequence source, + final int sStart, final int sEnd, + final Spanned dest, + final int dStart, final int dEnd) { + SpannableStringBuilder replacement = null; + int rIndex = 0; + final int dLength = dest.length(); + for (int sIndex = sStart; sIndex < sEnd; ++sIndex) { + final char c = source.charAt(sIndex); + final int dIndex = dStart + (sIndex - sStart); + // Restrict characters to those valid in interfaces. + // Ensure adding this character does not push the length over the limit. + if ((dIndex < Config.NAME_MAX_LENGTH && isAllowed(c)) && + dLength + (sIndex - sStart) < Config.NAME_MAX_LENGTH) { + ++rIndex; + } else { + if (replacement == null) + replacement = new SpannableStringBuilder(source, sStart, sEnd); + replacement.delete(rIndex, rIndex + 1); + } + } + return replacement; + } + + private boolean isAllowed(final char c) { + return Character.isLetterOrDigit(c) || "_=+.-".indexOf(c) >= 0; + } +} diff --git a/app/src/main/java/com/wireguard/config/Config.java b/app/src/main/java/com/wireguard/config/Config.java index b2885710..c7fdcc87 100644 --- a/app/src/main/java/com/wireguard/config/Config.java +++ b/app/src/main/java/com/wireguard/config/Config.java @@ -22,10 +22,11 @@ import java.util.regex.Pattern; public class Config extends BaseObservable implements Comparable, Copyable, Observable { + public static final int NAME_MAX_LENGTH = 16; private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9_=+.-]{1,16}$"); private static boolean isNameValid(final String name) { - return PATTERN.matcher(name).matches(); + return name.length() <= NAME_MAX_LENGTH && PATTERN.matcher(name).matches(); } private final Interface iface = new Interface(); diff --git a/app/src/main/res/layout/config_edit_fragment.xml b/app/src/main/res/layout/config_edit_fragment.xml index 4f48727c..fa936517 100644 --- a/app/src/main/res/layout/config_edit_fragment.xml +++ b/app/src/main/res/layout/config_edit_fragment.xml @@ -1,8 +1,13 @@ - + + + + + @@ -32,7 +37,8 @@ android:layout_height="wrap_content" android:layout_below="@+id/config_name_label" android:inputType="textCapWords" - android:text="@={config.name}" /> + android:text="@={config.name}" + app:filter="@{NameInputFilter.newInstance()}" /> + android:text="@={config.interface.privateKey}" + app:filter="@{KeyInputFilter.newInstance()}" />