Files
PowerToys/src/modules/launcher/Plugins/Microsoft.Plugin.Uri/UriHelper/ExtendedUriParser.cs

88 lines
3.3 KiB
C#
Raw Normal View History

// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
2021-07-05 16:26:31 +02:00
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Plugin.Uri.Interfaces;
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)
{
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)
const string schemeRegex = @"^([a-z][a-z0-9+\-.]*):";
if (input.EndsWith(":", StringComparison.OrdinalIgnoreCase)
&& !input.StartsWith("http", StringComparison.OrdinalIgnoreCase)
&& !input.Contains('/', StringComparison.OrdinalIgnoreCase)
&& !input.All(char.IsDigit)
&& Regex.IsMatch(input, schemeRegex))
{
result = new System.Uri(input);
isWebUri = false;
return true;
}
// Handle common cases UriBuilder does not handle
// Using CurrentCulture since this is a user typed string
if (input.EndsWith(":", StringComparison.CurrentCulture)
|| input.EndsWith(".", StringComparison.CurrentCulture)
2021-07-05 16:26:31 +02:00
|| input.EndsWith(":/", StringComparison.CurrentCulture)
|| input.EndsWith("://", StringComparison.CurrentCulture)
2021-07-05 16:26:31 +02:00
|| input.All(char.IsDigit))
{
result = default;
isWebUri = false;
return false;
}
try
{
var urlBuilder = new UriBuilder(input);
var hadDefaultPort = urlBuilder.Uri.IsDefaultPort;
urlBuilder.Port = hadDefaultPort ? -1 : urlBuilder.Port;
if (input.StartsWith("HTTP://", StringComparison.OrdinalIgnoreCase))
{
urlBuilder.Scheme = System.Uri.UriSchemeHttp;
isWebUri = true;
}
else if (input.Contains(':', StringComparison.OrdinalIgnoreCase) &&
!input.StartsWith("http", StringComparison.OrdinalIgnoreCase) &&
!input.Contains('[', StringComparison.OrdinalIgnoreCase))
{
// Do nothing, leave unchanged
isWebUri = false;
}
else
{
urlBuilder.Scheme = System.Uri.UriSchemeHttps;
isWebUri = true;
}
result = urlBuilder.Uri;
return true;
}
catch (UriFormatException)
{
result = default;
isWebUri = false;
return false;
}
}
}
}