@@ -27,7 +27,6 @@ import com.wireguard.config.Peer; | |||||
import java.net.InetAddress; | import java.net.InetAddress; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Locale; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
@@ -96,7 +95,7 @@ public final class GoBackend implements Backend { | |||||
@Override | @Override | ||||
public String getTypePrettyName() { | public String getTypePrettyName() { | ||||
return context.getResources().getString(R.string.type_name_go_userspace); | |||||
return context.getString(R.string.type_name_go_userspace); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -112,7 +111,7 @@ public final class GoBackend implements Backend { | |||||
if (state == originalState) | if (state == originalState) | ||||
return originalState; | return originalState; | ||||
if (state == State.UP && currentTunnel != null) | if (state == State.UP && currentTunnel != null) | ||||
throw new IllegalStateException(context.getResources().getString(R.string.multiple_tunnels_error)); | |||||
throw new IllegalStateException(context.getString(R.string.multiple_tunnels_error)); | |||||
Log.d(TAG, "Changing tunnel " + tunnel.getName() + " to state " + state); | Log.d(TAG, "Changing tunnel " + tunnel.getName() + " to state " + state); | ||||
setStateInternal(tunnel, tunnel.getConfig(), state); | setStateInternal(tunnel, tunnel.getConfig(), state); | ||||
return getState(tunnel); | return getState(tunnel); | ||||
@@ -124,10 +123,10 @@ public final class GoBackend implements Backend { | |||||
if (state == State.UP) { | if (state == State.UP) { | ||||
Log.i(TAG, "Bringing tunnel up"); | Log.i(TAG, "Bringing tunnel up"); | ||||
Objects.requireNonNull(config, context.getResources().getString(R.string.no_config_error)); | |||||
Objects.requireNonNull(config, context.getString(R.string.no_config_error)); | |||||
if (VpnService.prepare(context) != null) | if (VpnService.prepare(context) != null) | ||||
throw new Exception(context.getResources().getString(R.string.vpn_not_authed_error)); | |||||
throw new Exception(context.getString(R.string.vpn_not_authed_error)); | |||||
final VpnService service; | final VpnService service; | ||||
if (!vpnService.isDone()) | if (!vpnService.isDone()) | ||||
@@ -136,7 +135,7 @@ public final class GoBackend implements Backend { | |||||
try { | try { | ||||
service = vpnService.get(2, TimeUnit.SECONDS); | service = vpnService.get(2, TimeUnit.SECONDS); | ||||
} catch (final TimeoutException e) { | } catch (final TimeoutException e) { | ||||
throw new Exception(context.getResources().getString(R.string.vpn_start_error), e); | |||||
throw new Exception(context.getString(R.string.vpn_start_error), e); | |||||
} | } | ||||
if (currentTunnelHandle != -1) { | if (currentTunnelHandle != -1) { | ||||
@@ -174,12 +173,12 @@ public final class GoBackend implements Backend { | |||||
builder.setBlocking(true); | builder.setBlocking(true); | ||||
try (final ParcelFileDescriptor tun = builder.establish()) { | try (final ParcelFileDescriptor tun = builder.establish()) { | ||||
if (tun == null) | if (tun == null) | ||||
throw new Exception(context.getResources().getString(R.string.tun_create_error)); | |||||
throw new Exception(context.getString(R.string.tun_create_error)); | |||||
Log.d(TAG, "Go backend v" + wgVersion()); | Log.d(TAG, "Go backend v" + wgVersion()); | ||||
currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); | currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); | ||||
} | } | ||||
if (currentTunnelHandle < 0) | if (currentTunnelHandle < 0) | ||||
throw new Exception(String.format(Locale.getDefault(), context.getResources().getString(R.string.tunnel_on_error), currentTunnelHandle)); | |||||
throw new Exception(context.getString(R.string.tunnel_on_error, currentTunnelHandle)); | |||||
currentTunnel = tunnel; | currentTunnel = tunnel; | ||||
@@ -88,7 +88,7 @@ public final class WgQuickBackend implements Backend { | |||||
@Override | @Override | ||||
public String getTypePrettyName() { | public String getTypePrettyName() { | ||||
return context.getResources().getString(R.string.type_name_kernel_module); | |||||
return context.getString(R.string.type_name_kernel_module); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -96,7 +96,7 @@ public final class WgQuickBackend implements Backend { | |||||
final List<String> output = new ArrayList<>(); | final List<String> output = new ArrayList<>(); | ||||
if (Application.getRootShell() | if (Application.getRootShell() | ||||
.run(output, "cat /sys/module/wireguard/version") != 0 || output.isEmpty()) | .run(output, "cat /sys/module/wireguard/version") != 0 || output.isEmpty()) | ||||
throw new Exception(context.getResources().getString(R.string.module_version_error)); | |||||
throw new Exception(context.getString(R.string.module_version_error)); | |||||
return output.get(0); | return output.get(0); | ||||
} | } | ||||
@@ -128,6 +128,6 @@ public final class WgQuickBackend implements Backend { | |||||
// noinspection ResultOfMethodCallIgnored | // noinspection ResultOfMethodCallIgnored | ||||
tempFile.delete(); | tempFile.delete(); | ||||
if (result != 0) | if (result != 0) | ||||
throw new Exception(context.getResources().getString(R.string.tunnel_config_error)); | |||||
throw new Exception(context.getString(R.string.tunnel_config_error)); | |||||
} | } | ||||
} | } |
@@ -18,7 +18,6 @@ import java.io.FileNotFoundException; | |||||
import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
import java.util.Locale; | |||||
import java.util.Set; | import java.util.Set; | ||||
import java9.util.stream.Collectors; | import java9.util.stream.Collectors; | ||||
@@ -42,8 +41,7 @@ public final class FileConfigStore implements ConfigStore { | |||||
Log.d(TAG, "Creating configuration for tunnel " + name); | Log.d(TAG, "Creating configuration for tunnel " + name); | ||||
final File file = fileFor(name); | final File file = fileFor(name); | ||||
if (!file.createNewFile()) | if (!file.createNewFile()) | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.config_file_exists_error), file.getName())); | |||||
throw new IOException(context.getString(R.string.config_file_exists_error, file.getName())); | |||||
try (final FileOutputStream stream = new FileOutputStream(file, false)) { | try (final FileOutputStream stream = new FileOutputStream(file, false)) { | ||||
stream.write(config.toWgQuickString().getBytes(StandardCharsets.UTF_8)); | stream.write(config.toWgQuickString().getBytes(StandardCharsets.UTF_8)); | ||||
} | } | ||||
@@ -55,8 +53,7 @@ public final class FileConfigStore implements ConfigStore { | |||||
Log.d(TAG, "Deleting configuration for tunnel " + name); | Log.d(TAG, "Deleting configuration for tunnel " + name); | ||||
final File file = fileFor(name); | final File file = fileFor(name); | ||||
if (!file.delete()) | if (!file.delete()) | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.config_delete_error), file.getName())); | |||||
throw new IOException(context.getString(R.string.config_delete_error, file.getName())); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -84,13 +81,11 @@ public final class FileConfigStore implements ConfigStore { | |||||
final File file = fileFor(name); | final File file = fileFor(name); | ||||
final File replacementFile = fileFor(replacement); | final File replacementFile = fileFor(replacement); | ||||
if (!replacementFile.createNewFile()) | if (!replacementFile.createNewFile()) | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.config_exists_error), replacement)); | |||||
throw new IOException(context.getString(R.string.config_exists_error, replacement)); | |||||
if (!file.renameTo(replacementFile)) { | if (!file.renameTo(replacementFile)) { | ||||
if (!replacementFile.delete()) | if (!replacementFile.delete()) | ||||
Log.w(TAG, "Couldn't delete marker file for new name " + replacement); | Log.w(TAG, "Couldn't delete marker file for new name " + replacement); | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.config_rename_error), file.getName())); | |||||
throw new IOException(context.getString(R.string.config_rename_error, file.getName())); | |||||
} | } | ||||
} | } | ||||
@@ -99,8 +94,7 @@ public final class FileConfigStore implements ConfigStore { | |||||
Log.d(TAG, "Saving configuration for tunnel " + name); | Log.d(TAG, "Saving configuration for tunnel " + name); | ||||
final File file = fileFor(name); | final File file = fileFor(name); | ||||
if (!file.isFile()) | if (!file.isFile()) | ||||
throw new FileNotFoundException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.config_not_found_error), file.getName())); | |||||
throw new FileNotFoundException(context.getString(R.string.config_not_found_error, file.getName())); | |||||
try (final FileOutputStream stream = new FileOutputStream(file, false)) { | try (final FileOutputStream stream = new FileOutputStream(file, false)) { | ||||
stream.write(config.toWgQuickString().getBytes(StandardCharsets.UTF_8)); | stream.write(config.toWgQuickString().getBytes(StandardCharsets.UTF_8)); | ||||
} | } | ||||
@@ -24,7 +24,6 @@ import com.wireguard.config.ParseException; | |||||
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
import java.util.Locale; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
public class ConfigNamingDialogFragment extends DialogFragment { | public class ConfigNamingDialogFragment extends DialogFragment { | ||||
@@ -69,8 +68,7 @@ public class ConfigNamingDialogFragment extends DialogFragment { | |||||
try { | try { | ||||
config = Config.parse(new ByteArrayInputStream(getArguments().getString(KEY_CONFIG_TEXT).getBytes(StandardCharsets.UTF_8))); | config = Config.parse(new ByteArrayInputStream(getArguments().getString(KEY_CONFIG_TEXT).getBytes(StandardCharsets.UTF_8))); | ||||
} catch (final IOException | ParseException exception) { | } catch (final IOException | ParseException exception) { | ||||
throw new RuntimeException(String.format(Locale.getDefault(), | |||||
getResources().getString(R.string.invalid_config_error), getClass().getSimpleName()), exception); | |||||
throw new RuntimeException(getResources().getString(R.string.invalid_config_error, getClass().getSimpleName()), exception); | |||||
} | } | ||||
} | } | ||||
@@ -115,8 +115,7 @@ public class TunnelListFragment extends BaseFragment { | |||||
int idx = name.lastIndexOf('/'); | int idx = name.lastIndexOf('/'); | ||||
if (idx >= 0) { | if (idx >= 0) { | ||||
if (idx >= name.length() - 1) | if (idx >= name.length() - 1) | ||||
throw new IllegalArgumentException(String.format(Locale.getDefault(), | |||||
getResources().getString(R.string.illegal_filename_error), name)); | |||||
throw new IllegalArgumentException(getResources().getString(R.string.illegal_filename_error, name)); | |||||
name = name.substring(idx + 1); | name = name.substring(idx + 1); | ||||
} | } | ||||
boolean isZip = name.toLowerCase(Locale.ENGLISH).endsWith(".zip"); | boolean isZip = name.toLowerCase(Locale.ENGLISH).endsWith(".zip"); | ||||
@@ -45,7 +45,7 @@ public class LogExporterPreference extends Preference { | |||||
final File file = new File(path, "wireguard-log.txt"); | final File file = new File(path, "wireguard-log.txt"); | ||||
if (!path.isDirectory() && !path.mkdirs()) | if (!path.isDirectory() && !path.mkdirs()) | ||||
throw new IOException( | throw new IOException( | ||||
getContext().getResources().getString(R.string.create_output_dir_error)); | |||||
getContext().getString(R.string.create_output_dir_error)); | |||||
/* We would like to simply run `builder.redirectOutput(file);`, but this is API 26. | /* We would like to simply run `builder.redirectOutput(file);`, but this is API 26. | ||||
* Instead we have to do this dance, since logcat appends. | * Instead we have to do this dance, since logcat appends. | ||||
@@ -56,7 +56,7 @@ public class ZipExporterPreference extends Preference { | |||||
futureConfigs.add(tunnel.getConfigAsync().toCompletableFuture()); | futureConfigs.add(tunnel.getConfigAsync().toCompletableFuture()); | ||||
if (futureConfigs.isEmpty()) { | if (futureConfigs.isEmpty()) { | ||||
exportZipComplete(null, new IllegalArgumentException( | exportZipComplete(null, new IllegalArgumentException( | ||||
getContext().getResources().getString(R.string.no_tunnels_error))); | |||||
getContext().getString(R.string.no_tunnels_error))); | |||||
return; | return; | ||||
} | } | ||||
CompletableFuture.allOf(futureConfigs.toArray(new CompletableFuture[futureConfigs.size()])) | CompletableFuture.allOf(futureConfigs.toArray(new CompletableFuture[futureConfigs.size()])) | ||||
@@ -67,7 +67,7 @@ public class ZipExporterPreference extends Preference { | |||||
final File file = new File(path, "wireguard-export.zip"); | final File file = new File(path, "wireguard-export.zip"); | ||||
if (!path.isDirectory() && !path.mkdirs()) | if (!path.isDirectory() && !path.mkdirs()) | ||||
throw new IOException( | throw new IOException( | ||||
getContext().getResources().getString(R.string.create_output_dir_error)); | |||||
getContext().getString(R.string.create_output_dir_error)); | |||||
try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file))) { | try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file))) { | ||||
for (int i = 0; i < futureConfigs.size(); ++i) { | for (int i = 0; i < futureConfigs.size(); ++i) { | ||||
zip.putNextEntry(new ZipEntry(tunnels.get(i).getName() + ".conf")); | zip.putNextEntry(new ZipEntry(tunnels.get(i).getName() + ".conf")); | ||||
@@ -20,7 +20,6 @@ import java.io.InputStreamReader; | |||||
import java.io.OutputStreamWriter; | import java.io.OutputStreamWriter; | ||||
import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Locale; | |||||
import java.util.UUID; | import java.util.UUID; | ||||
/** | /** | ||||
@@ -124,10 +123,9 @@ public class RootShell { | |||||
} | } | ||||
} | } | ||||
if (markersSeen != 4) | if (markersSeen != 4) | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.marker_count_error), markersSeen)); | |||||
throw new IOException(context.getString(R.string.marker_count_error, markersSeen)); | |||||
if (errnoStdout != errnoStderr) | if (errnoStdout != errnoStderr) | ||||
throw new IOException(context.getResources().getString(R.string.exit_status_read_error)); | |||||
throw new IOException(context.getString(R.string.exit_status_read_error)); | |||||
Log.v(TAG, "exit: " + errnoStdout); | Log.v(TAG, "exit: " + errnoStdout); | ||||
return errnoStdout; | return errnoStdout; | ||||
} | } | ||||
@@ -140,9 +138,9 @@ public class RootShell { | |||||
if (isRunning()) | if (isRunning()) | ||||
return; | return; | ||||
if (!localBinaryDir.isDirectory() && !localBinaryDir.mkdirs()) | if (!localBinaryDir.isDirectory() && !localBinaryDir.mkdirs()) | ||||
throw new FileNotFoundException(context.getResources().getString(R.string.create_bin_dir_error)); | |||||
throw new FileNotFoundException(context.getString(R.string.create_bin_dir_error)); | |||||
if (!localTemporaryDir.isDirectory() && !localTemporaryDir.mkdirs()) | if (!localTemporaryDir.isDirectory() && !localTemporaryDir.mkdirs()) | ||||
throw new FileNotFoundException(context.getResources().getString(R.string.create_temp_dir_error)); | |||||
throw new FileNotFoundException(context.getString(R.string.create_temp_dir_error)); | |||||
try { | try { | ||||
final ProcessBuilder builder = new ProcessBuilder().command(SU); | final ProcessBuilder builder = new ProcessBuilder().command(SU); | ||||
builder.environment().put("LC_ALL", "C"); | builder.environment().put("LC_ALL", "C"); | ||||
@@ -172,8 +170,7 @@ public class RootShell { | |||||
if (line.contains("Permission denied")) | if (line.contains("Permission denied")) | ||||
throw new NoRootException(deviceNotRootedMessage); | throw new NoRootException(deviceNotRootedMessage); | ||||
} | } | ||||
throw new IOException(String.format(Locale.getDefault(), | |||||
context.getResources().getString(R.string.shell_start_error), process.exitValue())); | |||||
throw new IOException(context.getString(R.string.shell_start_error, process.exitValue())); | |||||
} | } | ||||
} catch (final IOException | NoRootException e) { | } catch (final IOException | NoRootException e) { | ||||
stop(); | stop(); | ||||
@@ -106,7 +106,7 @@ public final class ToolsInstaller { | |||||
} | } | ||||
if (!areToolsAvailable) | if (!areToolsAvailable) | ||||
throw new FileNotFoundException( | throw new FileNotFoundException( | ||||
context.getResources().getString(R.string.tools_unavailable_error)); | |||||
context.getString(R.string.tools_unavailable_error)); | |||||
} | } | ||||
} | } | ||||
@@ -30,9 +30,7 @@ public final class Config { | |||||
private final List<Peer> peers; | private final List<Peer> peers; | ||||
private Config(final Builder builder) { | private Config(final Builder builder) { | ||||
if (builder.interfaze == null) | |||||
throw new IllegalArgumentException("An [Interface] section is required"); | |||||
interfaze = builder.interfaze; | |||||
interfaze = Objects.requireNonNull(builder.interfaze, "An [Interface] section is required"); | |||||
// Defensively copy to ensure immutability even if the Builder is reused. | // Defensively copy to ensure immutability even if the Builder is reused. | ||||
peers = Collections.unmodifiableList(new ArrayList<>(builder.peers)); | peers = Collections.unmodifiableList(new ArrayList<>(builder.peers)); | ||||
} | } | ||||
@@ -189,6 +187,8 @@ public final class Config { | |||||
} | } | ||||
public Config build() { | public Config build() { | ||||
if (interfaze == null) | |||||
throw new IllegalArgumentException("An [Interface] section is required"); | |||||
return new Config(this); | return new Config(this); | ||||
} | } | ||||
@@ -44,14 +44,11 @@ public final class Interface { | |||||
private final Optional<Integer> mtu; | private final Optional<Integer> mtu; | ||||
private Interface(final Builder builder) { | private Interface(final Builder builder) { | ||||
if (builder.keyPair == null) | |||||
throw new IllegalArgumentException("Interfaces must have a private key"); | |||||
// Defensively copy to ensure immutability even if the Builder is reused. | // Defensively copy to ensure immutability even if the Builder is reused. | ||||
addresses = Collections.unmodifiableSet(new LinkedHashSet<>(builder.addresses)); | addresses = Collections.unmodifiableSet(new LinkedHashSet<>(builder.addresses)); | ||||
dnsServers = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsServers)); | dnsServers = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsServers)); | ||||
excludedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.excludedApplications)); | excludedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.excludedApplications)); | ||||
keyPair = builder.keyPair; | |||||
keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key"); | |||||
listenPort = builder.listenPort; | listenPort = builder.listenPort; | ||||
mtu = builder.mtu; | mtu = builder.mtu; | ||||
} | } | ||||
@@ -264,6 +261,8 @@ public final class Interface { | |||||
} | } | ||||
public Interface build() { | public Interface build() { | ||||
if (keyPair == null) | |||||
throw new IllegalArgumentException("Interfaces must have a private key"); | |||||
return new Interface(this); | return new Interface(this); | ||||
} | } | ||||
@@ -35,14 +35,12 @@ public final class Peer { | |||||
private final Key publicKey; | private final Key publicKey; | ||||
private Peer(final Builder builder) { | private Peer(final Builder builder) { | ||||
if (builder.publicKey == null) | |||||
throw new IllegalArgumentException("Peers must have a public key"); | |||||
// Defensively copy to ensure immutability even if the Builder is reused. | // Defensively copy to ensure immutability even if the Builder is reused. | ||||
allowedIps = Collections.unmodifiableSet(new LinkedHashSet<>(builder.allowedIps)); | allowedIps = Collections.unmodifiableSet(new LinkedHashSet<>(builder.allowedIps)); | ||||
endpoint = builder.endpoint; | endpoint = builder.endpoint; | ||||
persistentKeepalive = builder.persistentKeepalive; | persistentKeepalive = builder.persistentKeepalive; | ||||
preSharedKey = builder.preSharedKey; | preSharedKey = builder.preSharedKey; | ||||
publicKey = builder.publicKey; | |||||
publicKey = Objects.requireNonNull(builder.publicKey, "Peers must have a public key"); | |||||
} | } | ||||
/** | /** | ||||
@@ -226,6 +224,8 @@ public final class Peer { | |||||
} | } | ||||
public Peer build() { | public Peer build() { | ||||
if (publicKey == null) | |||||
throw new IllegalArgumentException("Peers must have a public key"); | |||||
return new Peer(this); | return new Peer(this); | ||||
} | } | ||||