mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
[PTRun][URL]Fix web link with ports support (#19809)
* [PT Run] Fix web link with ports support (#14260) * URL in the format of `domain:port` now directs to default browser * Add tests to verify web link with ports scenario * Fix test case and scenario where mismatching schema and port for IPv6 does not result in correct output * [PT Run][Tests] Change and add more UriParser Tests * Specifically of note is line 56, where [IPv6]:80 diverts to https instead of http. * [PT Run][Tests] Add UriParser tests * Add more tests targeting port handling * [PT Run] Fix http handling * This also fixes oddity with IPv4 and IPv6 handling * [PT Run] Add second results depending on condition * Test: update all test to reflect updated functions & add a little more tests * Update function to show two results when URI is in the format of `domain:port` (situation where it can also be `schema:path`) * Update regex style to follow previous code * [PT Run] Change tests and filter localhost from certain results * Add tests for 127.0.0.1, localhost, and ::1 * Move test around into more logical arrangement * Filter localhost out from showing double results * [PT Run] Fix spelling on comments * [PT Run] Add some words to expect.txt * [PT Toys] Clarify comment regarding [::] Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * [PT Run] Remove tests regarding tel protocol * [PT Run] Clarify UriParser parameter * [PT Run] Add UriParser tests for tel protocol * Current code has a regression bug where tel:xxxx, if xxxx is more than 65536 it will break. Will fix in follow up commit. * [PT Run] Refactor ExtendedUriParser and its tests * Remove `isWebUri` from ExtendedUriParser, keeping only webUri and systemUri * Tel protocol regression bug still exists * [PT Run] Fix wrong icon when webUri result * [PT Run] Fix regression bug for tel protocol * Tel protocol will sometimes bug out when tel:xxxx if xxxxx is more than 65535, as UriBuilder will throw error thinking the port number has been exceeded * [PT Toy] Fix tel test * [PT Run] Changes to tests * Add test for application uri to include ports, for all non-protocol, http and https variants * Rearrange some more test to make more logical sense, and add comments * [PT Run] Simplify code * Move webUri and systemUri to be global, as per htcfreek's recommendation * Add comment to empty catch * Change null to default * [PT Toy] Update test name Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * [PT Toy] Change result prompt when empty string * [PT Toy] Fix typo in comment * [PT Toy] Simplify line * [PT Toy] Change result prompt when empty string
This commit is contained in:
@@ -6,6 +6,6 @@ namespace Microsoft.Plugin.Uri.Interfaces
|
||||
{
|
||||
public interface IUriParser
|
||||
{
|
||||
bool TryParse(string input, out System.Uri result, out bool isWebUri);
|
||||
bool TryParse(string input, out System.Uri webUri, out System.Uri systemUri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.Plugin.Uri
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = Properties.Resources.Microsoft_plugin_uri_open,
|
||||
Title = Properties.Resources.Microsoft_plugin_uri_default_browser,
|
||||
SubTitle = BrowserInfo.Path,
|
||||
IcoPath = DefaultIconPath,
|
||||
Action = action =>
|
||||
@@ -70,34 +70,54 @@ namespace Microsoft.Plugin.Uri
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(query?.Search)
|
||||
&& _uriParser.TryParse(query.Search, out var uriResult, out var isWebUri)
|
||||
&& _uriResolver.IsValidHost(uriResult))
|
||||
&& _uriParser.TryParse(query.Search, out var webUriResult, out var systemUriResult)
|
||||
&& _uriResolver.IsValidHost(webUriResult))
|
||||
{
|
||||
var uriResultString = uriResult.ToString();
|
||||
var isWebUriBool = isWebUri;
|
||||
|
||||
results.Add(new Result
|
||||
if (webUriResult is not null)
|
||||
{
|
||||
Title = uriResultString,
|
||||
SubTitle = isWebUriBool
|
||||
? Properties.Resources.Microsoft_plugin_uri_website
|
||||
: Properties.Resources.Microsoft_plugin_uri_open,
|
||||
IcoPath = isWebUriBool && BrowserInfo.IconPath != null
|
||||
? BrowserInfo.IconPath
|
||||
: DefaultIconPath,
|
||||
Action = action =>
|
||||
var resultString = webUriResult.ToString();
|
||||
results.Add(new Result
|
||||
{
|
||||
if (!Helper.OpenInShell(uriResultString))
|
||||
Title = resultString,
|
||||
SubTitle = Properties.Resources.Microsoft_plugin_uri_website,
|
||||
IcoPath = BrowserInfo.IconPath,
|
||||
Action = action =>
|
||||
{
|
||||
var title = $"Plugin: {Properties.Resources.Microsoft_plugin_uri_plugin_name}";
|
||||
var message = $"{Properties.Resources.Microsoft_plugin_uri_open_failed}: {uriResultString}";
|
||||
Context.API.ShowMsg(title, message);
|
||||
return false;
|
||||
}
|
||||
if (!Helper.OpenInShell(resultString))
|
||||
{
|
||||
var title = $"Plugin: {Properties.Resources.Microsoft_plugin_uri_plugin_name}";
|
||||
var message = $"{Properties.Resources.Microsoft_plugin_uri_open_failed}: {resultString}";
|
||||
Context.API.ShowMsg(title, message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (systemUriResult is not null)
|
||||
{
|
||||
var resultString = systemUriResult.ToString();
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = resultString,
|
||||
SubTitle = Properties.Resources.Microsoft_plugin_uri_open,
|
||||
IcoPath = DefaultIconPath,
|
||||
Action = action =>
|
||||
{
|
||||
if (!Helper.OpenInShell(resultString))
|
||||
{
|
||||
var title = $"Plugin: {Properties.Resources.Microsoft_plugin_uri_plugin_name}";
|
||||
var message = $"{Properties.Resources.Microsoft_plugin_uri_open_failed}: {resultString}";
|
||||
Context.API.ShowMsg(title, message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
|
||||
@@ -12,18 +12,19 @@ namespace Microsoft.Plugin.Uri.UriHelper
|
||||
public class ExtendedUriParser : IUriParser
|
||||
{
|
||||
// When updating this method, also update the local method IsUri() in Community.PowerToys.Run.Plugin.WebSearch.Main.Query
|
||||
public bool TryParse(string input, out System.Uri result, out bool isWebUri)
|
||||
public bool TryParse(string input, out System.Uri webUri, out System.Uri systemUri)
|
||||
{
|
||||
webUri = default;
|
||||
systemUri = default;
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
result = default;
|
||||
isWebUri = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handling URL with only scheme, typically mailto or application uri.
|
||||
// Do nothing, return the result without urlBuilder
|
||||
// And check if scheme match REC3986 (issue #15035)
|
||||
// And check if scheme match RFC3986 (issue #15035)
|
||||
const string schemeRegex = @"^([a-z][a-z0-9+\-.]*):";
|
||||
if (input.EndsWith(":", StringComparison.OrdinalIgnoreCase)
|
||||
&& !input.StartsWith("http", StringComparison.OrdinalIgnoreCase)
|
||||
@@ -31,8 +32,7 @@ namespace Microsoft.Plugin.Uri.UriHelper
|
||||
&& !input.All(char.IsDigit)
|
||||
&& Regex.IsMatch(input, schemeRegex))
|
||||
{
|
||||
result = new System.Uri(input);
|
||||
isWebUri = false;
|
||||
systemUri = new System.Uri(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,42 +44,66 @@ namespace Microsoft.Plugin.Uri.UriHelper
|
||||
|| input.EndsWith("://", StringComparison.CurrentCulture)
|
||||
|| input.All(char.IsDigit))
|
||||
{
|
||||
result = default;
|
||||
isWebUri = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string isDomainPortRegex = @"^[\w\.]+:\d+";
|
||||
string isIPv6PortRegex = @"^\[([\w:]+:+)+[\w]+\]:\d+";
|
||||
var urlBuilder = new UriBuilder(input);
|
||||
var hadDefaultPort = urlBuilder.Uri.IsDefaultPort;
|
||||
urlBuilder.Port = hadDefaultPort ? -1 : urlBuilder.Port;
|
||||
urlBuilder.Port = urlBuilder.Uri.IsDefaultPort ? -1 : urlBuilder.Port;
|
||||
|
||||
if (input.StartsWith("HTTP://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
urlBuilder.Scheme = System.Uri.UriSchemeHttp;
|
||||
isWebUri = true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, isDomainPortRegex) ||
|
||||
Regex.IsMatch(input, isIPv6PortRegex))
|
||||
{
|
||||
var secondUrlBuilder = urlBuilder;
|
||||
|
||||
try
|
||||
{
|
||||
urlBuilder = new UriBuilder("https://" + input);
|
||||
|
||||
if (urlBuilder.Port == 80)
|
||||
{
|
||||
urlBuilder.Scheme = System.Uri.UriSchemeHttp;
|
||||
}
|
||||
}
|
||||
catch (UriFormatException)
|
||||
{
|
||||
// This handles the situation in tel:xxxx and others
|
||||
// When xxxx > 65535, it will throw UriFormatException
|
||||
// The catch ensures it will at least still try to return a systemUri
|
||||
}
|
||||
|
||||
string singleLabelRegex = @"[\.:]+|^http$|^https$|^localhost$";
|
||||
systemUri = Regex.IsMatch(urlBuilder.Host, singleLabelRegex) ? null : secondUrlBuilder.Uri;
|
||||
}
|
||||
else if (input.Contains(':', StringComparison.OrdinalIgnoreCase) &&
|
||||
!input.StartsWith("http", StringComparison.OrdinalIgnoreCase) &&
|
||||
!input.Contains('[', StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Do nothing, leave unchanged
|
||||
isWebUri = false;
|
||||
systemUri = urlBuilder.Uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
urlBuilder.Scheme = System.Uri.UriSchemeHttps;
|
||||
isWebUri = true;
|
||||
}
|
||||
|
||||
result = urlBuilder.Uri;
|
||||
if (urlBuilder.Scheme.Equals(System.Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
|
||||
urlBuilder.Scheme.Equals(System.Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
webUri = urlBuilder.Uri;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (UriFormatException)
|
||||
{
|
||||
result = default;
|
||||
isWebUri = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user