diff --git a/app/src/main/java/com/limelight/preferences/AddComputerManually.java b/app/src/main/java/com/limelight/preferences/AddComputerManually.java index e2d02fb2..febb6558 100644 --- a/app/src/main/java/com/limelight/preferences/AddComputerManually.java +++ b/app/src/main/java/com/limelight/preferences/AddComputerManually.java @@ -98,8 +98,31 @@ public class AddComputerManually extends Activity { } } + private URI parseRawUserInputToUri(String rawUserInput) { + try { + // Try adding a scheme and parsing the remaining input. + // This handles input like 127.0.0.1:47989, [::1], [::1]:47989, and 127.0.0.1. + URI uri = new URI("moonlight://" + rawUserInput); + if (uri.getHost() != null && !uri.getHost().isEmpty()) { + return uri; + } + } catch (URISyntaxException ignored) {} + + try { + // Attempt to escape the input as an IPv6 literal. + // This handles input like ::1. + URI uri = new URI("moonlight://[" + rawUserInput + "]"); + if (uri.getHost() != null && !uri.getHost().isEmpty()) { + return uri; + } + } catch (URISyntaxException ignored) {} + + return null; + } + private void doAddPc(String rawUserInput) throws InterruptedException { boolean wrongSiteLocal = false; + boolean invalidInput = false; boolean success; int portTestResult; @@ -109,26 +132,26 @@ public class AddComputerManually extends Activity { try { ComputerDetails details = new ComputerDetails(); - // Use URI-style parsing for the host address input - URI uri = new URI("moonlight://" + rawUserInput); + // Check if we parsed a host address successfully + URI uri = parseRawUserInputToUri(rawUserInput); + if (uri != null && uri.getHost() != null && !uri.getHost().isEmpty()) { + String host = uri.getHost(); + int port = uri.getPort(); - String host = uri.getHost(); - int port = uri.getPort(); + // If a port was not specified, use the default + if (port == -1) { + port = NvHTTP.DEFAULT_HTTP_PORT; + } - // URI allows empty hosts, but we don't want that - if (host == null || host.isEmpty()) { - throw new URISyntaxException(rawUserInput, "Host failed to parse"); - } - - // If a port was not specified, use the default - if (port == -1) { - port = NvHTTP.DEFAULT_HTTP_PORT; - } - - details.manualAddress = new ComputerDetails.AddressTuple(host, port); - success = managerBinder.addComputerBlocking(details); - if (!success){ - wrongSiteLocal = isWrongSubnetSiteLocalAddress(host); + details.manualAddress = new ComputerDetails.AddressTuple(host, port); + success = managerBinder.addComputerBlocking(details); + if (!success){ + wrongSiteLocal = isWrongSubnetSiteLocalAddress(host); + } + } else { + // Invalid user input + success = false; + invalidInput = true; } } catch (InterruptedException e) { // Propagate the InterruptedException to the caller for proper handling @@ -139,13 +162,11 @@ public class AddComputerManually extends Activity { // https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705 e.printStackTrace(); success = false; - } catch (URISyntaxException e) { - e.printStackTrace(); - success = false; + invalidInput = true; } // Keep the SpinnerDialog open while testing connectivity - if (!success && !wrongSiteLocal) { + if (!success && !wrongSiteLocal && !invalidInput) { // Run the test before dismissing the spinner because it can take a few seconds. portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443, MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989); @@ -156,7 +177,10 @@ public class AddComputerManually extends Activity { dialog.dismiss(); - if (wrongSiteLocal) { + if (invalidInput) { + Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_unknown_host), false); + } + else if (wrongSiteLocal) { Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false); } else if (!success) {