diff --git a/Flow.Launcher.Test/Plugins/UrlPluginTest.cs b/Flow.Launcher.Test/Plugins/UrlPluginTest.cs index f0d919bbe..38d94264c 100644 --- a/Flow.Launcher.Test/Plugins/UrlPluginTest.cs +++ b/Flow.Launcher.Test/Plugins/UrlPluginTest.cs @@ -54,14 +54,17 @@ namespace Flow.Launcher.Test.Plugins [TestCase("http://example.com/path")] [TestCase("https://example.com/path?query=1")] [TestCase("192.168.1.1/path/to/resource")] + [TestCase("192.168.1.1/path/to/resource?query=1")] [TestCase("localhost:8080/api/endpoint")] [TestCase("http://localhost/path")] [TestCase("[::1]/path")] + [TestCase("[2001:db8::1]/path?query=1")] public void WhenValidUrlThenIsUrlReturnsTrue(string url) { Assert.That(plugin.IsURL(url), Is.True); } + [TestCase("2001:db8::1/path")] [TestCase("wwww")] [TestCase("wwww.c")] [TestCase("not a url")] diff --git a/Plugins/Flow.Launcher.Plugin.Url/Main.cs b/Plugins/Flow.Launcher.Plugin.Url/Main.cs index c5036baa6..cabf0beea 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Main.cs @@ -94,8 +94,25 @@ namespace Flow.Launcher.Plugin.Url // Check if it's a bare IP address with optional port, path, query, or fragment var ipPart = input.Split('/', '?', '#')[0]; // Remove path, query, and fragment - if (IPEndPoint.TryParse(ipPart, out var endpoint) && !endpoint.Address.Equals(IPAddress.Any) && !endpoint.Address.Equals(IPAddress.IPv6Any)) + if (IPEndPoint.TryParse(ipPart, out var endpoint)) + { + switch (endpoint.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + return !endpoint.Address.Equals(IPAddress.Any); + case System.Net.Sockets.AddressFamily.InterNetworkV6: + if (input.Contains('/') || input.Contains('?') || input.Contains('#')) + { + // Check if IPv6 address is properly bracketed + var bracketStart = input.IndexOf('['); + var bracketEnd = input.IndexOf(']'); + if (bracketStart == -1 || bracketEnd == -1 || bracketStart > bracketEnd) + return false; + } + return !endpoint.Address.Equals(IPAddress.IPv6Any); + } return true; + } // Add protocol if missing for Uri validation var urlToValidate = UrlSchemes.Any(s => input.StartsWith(s, StringComparison.OrdinalIgnoreCase)) @@ -104,6 +121,7 @@ namespace Flow.Launcher.Plugin.Url if (!Uri.TryCreate(urlToValidate, UriKind.Absolute, out var uri)) return false; + // Validate protocol if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps && uri.Scheme != Uri.UriSchemeFtp)