Extract error messages to string resources

Useful for validation errors and localisation later on

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2018-08-01 02:47:34 +05:30 committed by Jason A. Donenfeld
parent 85462de254
commit c38f6c471d
7 changed files with 47 additions and 15 deletions

View File

@ -15,6 +15,7 @@ import android.support.annotation.Nullable;
import com.wireguard.android.Application; import com.wireguard.android.Application;
import com.wireguard.android.BR; import com.wireguard.android.BR;
import com.wireguard.android.R;
import com.wireguard.android.configStore.ConfigStore; import com.wireguard.android.configStore.ConfigStore;
import com.wireguard.android.model.Tunnel.State; import com.wireguard.android.model.Tunnel.State;
import com.wireguard.android.model.Tunnel.Statistics; import com.wireguard.android.model.Tunnel.Statistics;
@ -46,6 +47,7 @@ public final class TunnelManager extends BaseObservable {
private static final String KEY_RUNNING_TUNNELS = "enabled_configs"; private static final String KEY_RUNNING_TUNNELS = "enabled_configs";
private final ConfigStore configStore; private final ConfigStore configStore;
private final Context context = Application.get();
private final CompletableFuture<ObservableSortedKeyedList<String, Tunnel>> completableTunnels = new CompletableFuture<>(); private final CompletableFuture<ObservableSortedKeyedList<String, Tunnel>> completableTunnels = new CompletableFuture<>();
private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR); private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR);
@Nullable private Tunnel lastUsedTunnel; @Nullable private Tunnel lastUsedTunnel;
@ -64,9 +66,9 @@ public final class TunnelManager extends BaseObservable {
public CompletionStage<Tunnel> create(final String name, @Nullable final Config config) { public CompletionStage<Tunnel> create(final String name, @Nullable final Config config) {
if (Tunnel.isNameInvalid(name)) if (Tunnel.isNameInvalid(name))
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name")); return CompletableFuture.failedFuture(new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_name)));
if (tunnels.containsKey(name)) { if (tunnels.containsKey(name)) {
final String message = "Tunnel " + name + " already exists"; final String message = context.getString(R.string.tunnel_error_already_exists, name);
return CompletableFuture.failedFuture(new IllegalArgumentException(message)); return CompletableFuture.failedFuture(new IllegalArgumentException(message));
} }
return Application.getAsyncWorker().supplyAsync(() -> configStore.create(name, config)) return Application.getAsyncWorker().supplyAsync(() -> configStore.create(name, config))
@ -212,9 +214,9 @@ public final class TunnelManager extends BaseObservable {
CompletionStage<String> setTunnelName(final Tunnel tunnel, final String name) { CompletionStage<String> setTunnelName(final Tunnel tunnel, final String name) {
if (Tunnel.isNameInvalid(name)) if (Tunnel.isNameInvalid(name))
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name")); return CompletableFuture.failedFuture(new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_name)));
if (tunnels.containsKey(name)) { if (tunnels.containsKey(name)) {
final String message = "Tunnel " + name + " already exists"; final String message = context.getString(R.string.tunnel_error_already_exists, name);
return CompletableFuture.failedFuture(new IllegalArgumentException(message)); return CompletableFuture.failedFuture(new IllegalArgumentException(message));
} }
final State originalState = tunnel.getState(); final State originalState = tunnel.getState();

View File

@ -6,6 +6,7 @@
package com.wireguard.config; package com.wireguard.config;
import android.content.Context;
import android.databinding.BaseObservable; import android.databinding.BaseObservable;
import android.databinding.Bindable; import android.databinding.Bindable;
import android.databinding.ObservableArrayList; import android.databinding.ObservableArrayList;
@ -15,6 +16,8 @@ import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.android.databinding.library.baseAdapters.BR; import com.android.databinding.library.baseAdapters.BR;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -43,6 +46,7 @@ public class Config {
public static Config from(final BufferedReader reader) throws IOException { public static Config from(final BufferedReader reader) throws IOException {
final Config config = new Config(); final Config config = new Config();
final Context context = Application.get();
Peer currentPeer = null; Peer currentPeer = null;
String line; String line;
boolean inInterfaceSection = false; boolean inInterfaceSection = false;
@ -65,11 +69,11 @@ public class Config {
} else if (currentPeer != null) { } else if (currentPeer != null) {
currentPeer.parse(line); currentPeer.parse(line);
} else { } else {
throw new IllegalArgumentException("Invalid configuration line: " + line); throw new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_config_line, line));
} }
} }
if (!inInterfaceSection && currentPeer == null) { if (!inInterfaceSection && currentPeer == null) {
throw new IllegalArgumentException("Could not find any config information"); throw new IllegalArgumentException(context.getString(R.string.tunnel_error_no_config_information));
} }
return config; return config;
} }

View File

@ -8,6 +8,9 @@ package com.wireguard.config;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.InetAddress; import java.net.InetAddress;
@ -30,7 +33,7 @@ public final class InetAddresses {
public static InetAddress parse(@Nullable final String address) { public static InetAddress parse(@Nullable final String address) {
if (address == null || address.isEmpty()) if (address == null || address.isEmpty())
throw new IllegalArgumentException("Empty address"); throw new IllegalArgumentException(Application.get().getString(R.string.tunnel_error_empty_inetaddress));
try { try {
return (InetAddress) PARSER_METHOD.invoke(null, address); return (InetAddress) PARSER_METHOD.invoke(null, address);
} catch (final IllegalAccessException | InvocationTargetException e) { } catch (final IllegalAccessException | InvocationTargetException e) {

View File

@ -6,13 +6,16 @@
package com.wireguard.config; package com.wireguard.config;
import android.content.Context;
import android.databinding.BaseObservable; import android.databinding.BaseObservable;
import android.databinding.Bindable; import android.databinding.Bindable;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.wireguard.android.Application;
import com.wireguard.android.BR; import com.wireguard.android.BR;
import com.wireguard.android.R;
import com.wireguard.crypto.Keypair; import com.wireguard.crypto.Keypair;
import java.net.InetAddress; import java.net.InetAddress;
@ -31,6 +34,7 @@ public class Interface {
@Nullable private Keypair keypair; @Nullable private Keypair keypair;
private int listenPort; private int listenPort;
private int mtu; private int mtu;
private final Context context = Application.get();
public Interface() { public Interface() {
addressList = new ArrayList<>(); addressList = new ArrayList<>();
@ -42,7 +46,7 @@ public class Interface {
if (addresses != null && addresses.length > 0) { if (addresses != null && addresses.length > 0) {
for (final String addr : addresses) { for (final String addr : addresses) {
if (addr.isEmpty()) if (addr.isEmpty())
throw new IllegalArgumentException("Address is empty"); throw new IllegalArgumentException(context.getString(R.string.tunnel_error_empty_interface_address));
addressList.add(new InetNetwork(addr)); addressList.add(new InetNetwork(addr));
} }
} }
@ -141,7 +145,7 @@ public class Interface {
public void parse(final String line) { public void parse(final String line) {
final Attribute key = Attribute.match(line); final Attribute key = Attribute.match(line);
if (key == null) if (key == null)
throw new IllegalArgumentException(String.format("Unable to parse line: \"%s\"", line)); throw new IllegalArgumentException(String.format(context.getString(R.string.tunnel_error_interface_parse_failed), line));
switch (key) { switch (key) {
case ADDRESS: case ADDRESS:
addAddresses(key.parseList(line)); addAddresses(key.parseList(line));

View File

@ -6,6 +6,7 @@
package com.wireguard.config; package com.wireguard.config;
import android.content.Context;
import android.databinding.BaseObservable; import android.databinding.BaseObservable;
import android.databinding.Bindable; import android.databinding.Bindable;
import android.os.Parcel; import android.os.Parcel;
@ -13,6 +14,8 @@ import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.android.databinding.library.baseAdapters.BR; import com.android.databinding.library.baseAdapters.BR;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.crypto.KeyEncoding; import com.wireguard.crypto.KeyEncoding;
import java.net.Inet6Address; import java.net.Inet6Address;
@ -38,6 +41,7 @@ public class Peer {
private int persistentKeepalive; private int persistentKeepalive;
@Nullable private String preSharedKey; @Nullable private String preSharedKey;
@Nullable private String publicKey; @Nullable private String publicKey;
private final Context context = Application.get();
public Peer() { public Peer() {
allowedIPsList = new ArrayList<>(); allowedIPsList = new ArrayList<>();
@ -117,7 +121,7 @@ public class Peer {
public void parse(final String line) { public void parse(final String line) {
final Attribute key = Attribute.match(line); final Attribute key = Attribute.match(line);
if (key == null) if (key == null)
throw new IllegalArgumentException(String.format("Unable to parse line: \"%s\"", line)); throw new IllegalArgumentException(context.getString(R.string.tunnel_error_interface_parse_failed, line));
switch (key) { switch (key) {
case ALLOWED_IPS: case ALLOWED_IPS:
addAllowedIPs(key.parseList(line)); addAllowedIPs(key.parseList(line));
@ -152,7 +156,7 @@ public class Peer {
if (endpoint != null && !endpoint.isEmpty()) { if (endpoint != null && !endpoint.isEmpty()) {
final InetSocketAddress constructedEndpoint; final InetSocketAddress constructedEndpoint;
if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1) if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1)
throw new IllegalArgumentException("Forbidden characters in endpoint"); throw new IllegalArgumentException(context.getString(R.string.tunnel_error_forbidden_endpoint_chars));
final URI uri; final URI uri;
try { try {
uri = new URI("wg://" + endpoint); uri = new URI("wg://" + endpoint);
@ -253,7 +257,7 @@ public class Peer {
parent.setPreSharedKey(preSharedKey); parent.setPreSharedKey(preSharedKey);
parent.setPublicKey(publicKey); parent.setPublicKey(publicKey);
if (parent.getPublicKey() == null) if (parent.getPublicKey() == null)
throw new IllegalArgumentException("Peer public key may not be empty"); throw new IllegalArgumentException(Application.get().getString(R.string.tunnel_error_empty_peer_public_key));
loadData(parent); loadData(parent);
notifyChange(); notifyChange();
} }

View File

@ -5,6 +5,9 @@
package com.wireguard.crypto; package com.wireguard.crypto;
import com.wireguard.android.Application;
import com.wireguard.android.R;
/** /**
* This is a specialized constant-time base64 and hex implementation that resists side-channel attacks. * This is a specialized constant-time base64 and hex implementation that resists side-channel attacks.
*/ */
@ -15,11 +18,11 @@ public final class KeyEncoding {
public static final int KEY_LENGTH_BASE64 = 44; public static final int KEY_LENGTH_BASE64 = 44;
public static final int KEY_LENGTH_HEX = 64; public static final int KEY_LENGTH_HEX = 64;
private static final String KEY_LENGTH_BASE64_EXCEPTION_MESSAGE = private static final String KEY_LENGTH_BASE64_EXCEPTION_MESSAGE =
"WireGuard base64 keys must be 44 characters encoding 32 bytes"; Application.get().getString(R.string.key_length_base64_exception_message);
private static final String KEY_LENGTH_EXCEPTION_MESSAGE = private static final String KEY_LENGTH_EXCEPTION_MESSAGE =
"WireGuard keys must be 32 bytes"; Application.get().getString(R.string.key_length_exception_message);
private static final String KEY_LENGTH_HEX_EXCEPTION_MESSAGE = private static final String KEY_LENGTH_HEX_EXCEPTION_MESSAGE =
"WireGuard hex keys must be 64 characters encoding 32 bytes"; Application.get().getString(R.string.key_length_hex_exception_message);
private KeyEncoding() { private KeyEncoding() {
// Prevent instantiation. // Prevent instantiation.

View File

@ -97,6 +97,18 @@
<string name="tunnel_name">Tunnel Name</string> <string name="tunnel_name">Tunnel Name</string>
<string name="tunnel_rename_error">Unable to rename tunnel: %s</string> <string name="tunnel_rename_error">Unable to rename tunnel: %s</string>
<string name="tunnel_rename_success">Successfully renamed tunnel to “%s”</string> <string name="tunnel_rename_success">Successfully renamed tunnel to “%s”</string>
<string name="tunnel_error_invalid_name">Invalid name</string>
<string name="tunnel_error_already_exists">Tunnel %s already exists</string>
<string name="tunnel_error_empty_inetaddress">Empty address</string>
<string name="tunnel_error_empty_interface_address">Address is empty</string>
<string name="tunnel_error_interface_parse_failed">Unable to parse line: “%s”</string>
<string name="tunnel_error_forbidden_endpoint_chars">Forbidden characters in endpoint</string>
<string name="tunnel_error_empty_peer_public_key">Peer public key may not be empty</string>
<string name="tunnel_error_invalid_config_line">Invalid configuration line: %s</string>
<string name="tunnel_error_no_config_information">Could not find any config information</string>
<string name="key_length_base64_exception_message">WireGuard base64 keys must be 44 characters encoding 32 bytes</string>
<string name="key_length_exception_message">WireGuard keys must be 32 bytes</string>
<string name="key_length_hex_exception_message">WireGuard hex keys must be 64 characters encoding 32 bytes</string>
<string name="version_title">WireGuard for Android v%s"</string> <string name="version_title">WireGuard for Android v%s"</string>
<string name="version_summary">%s backend v%s</string> <string name="version_summary">%s backend v%s</string>
<string name="version_summary_checking">Checking %s backend version</string> <string name="version_summary_checking">Checking %s backend version</string>