mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 10:16:24 +02:00
[PTRun][ValueGenerator]Add URI/URL features (#30648)
* move existing generator classes * add new generators * implement new generators * fixes * improvements * shorten query tags * make spellcheck happy * add tests * dev docs * fix typos * fix tests
This commit is contained in:
@@ -30,12 +30,23 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests
|
||||
[DataRow("base99 abc", null)]
|
||||
[DataRow("base64s abc", null)]
|
||||
[DataRow("base64d abc=", typeof(Base64.Base64DecodeRequest))]
|
||||
public void ParserTest(string input, Type? expectedRequestType)
|
||||
[DataRow("url http://googl.de/u oii d", typeof(Uri.UrlEncodeRequest))]
|
||||
[DataRow("urld http://googl.de/u oii d=oo", typeof(Uri.UrlDecodeRequest))]
|
||||
[DataRow("esc:data jjdje332j 3 3l2jl32", typeof(Uri.DataEscapeRequest))]
|
||||
[DataRow("esc:hex d", typeof(Uri.HexEscapeRequest))]
|
||||
[DataRow("esc:hex 4", typeof(Uri.HexEscapeRequest))]
|
||||
[DataRow("esc:hex ", typeof(Uri.HexEscapeRequest), true)]
|
||||
[DataRow("esc:hex z44", typeof(Uri.HexEscapeRequest), true)]
|
||||
[DataRow("uesc:data jjdje332j 3 3l2jl32", typeof(Uri.DataUnescapeRequest))]
|
||||
[DataRow("uesc:hex %21", typeof(Uri.HexUnescapeRequest))]
|
||||
[DataRow("uesc:hex 4", typeof(Uri.HexUnescapeRequest))]
|
||||
[DataRow("uesc:hex ", typeof(Uri.HexUnescapeRequest))]
|
||||
[DataRow("uesc:hex z44", typeof(Uri.HexUnescapeRequest))]
|
||||
public void ParserTest(string input, Type? expectedRequestType, bool expectException = false)
|
||||
{
|
||||
var parser = new InputParser();
|
||||
var query = new Query(input);
|
||||
|
||||
var expectException = false;
|
||||
string? command = null;
|
||||
if (query.Terms.Count == 0)
|
||||
{
|
||||
@@ -79,15 +90,24 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests
|
||||
private static bool CommandIsKnown(string command)
|
||||
{
|
||||
string[] hashes = new string[] { "md5", "sha1", "sha256", "sha384", "sha512", "base64", "base64d" };
|
||||
|
||||
if (hashes.Contains(command.ToLowerInvariant()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Regex regex = new Regex("^(guid|uuid)([1345]{0,1}|v[1345]{1})$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
Regex regexGuiUUID = new Regex("^(guid|uuid)([1345]{0,1}|v[1345]{1})$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
if (regexGuiUUID.IsMatch(command))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return regex.IsMatch(command);
|
||||
string[] uriCommands = new string[] { "url", "urld", "esc:hex", "uesc:hex", "esc:data", "uesc:data" };
|
||||
if (uriCommands.Contains(command.ToLowerInvariant()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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;
|
||||
using System.Text;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class DataEscapeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Data string escaped";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToEscape { get; set; }
|
||||
|
||||
public DataEscapeRequest(string dataToEscape)
|
||||
{
|
||||
DataToEscape = dataToEscape ?? throw new ArgumentNullException(nameof(dataToEscape));
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
Result = Encoding.UTF8.GetBytes(System.Uri.EscapeDataString(DataToEscape));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class DataUnescapeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Data string unescaped";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToUnescape { get; set; }
|
||||
|
||||
public DataUnescapeRequest(string dataToUnescape)
|
||||
{
|
||||
DataToUnescape = dataToUnescape ?? throw new ArgumentNullException(nameof(dataToUnescape));
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
Result = Encoding.UTF8.GetBytes(System.Uri.UnescapeDataString(DataToUnescape));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
if (Result != null)
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class HexEscapeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Hex escaped char";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToEscape { get; set; }
|
||||
|
||||
public HexEscapeRequest(string dataToEscape)
|
||||
{
|
||||
DataToEscape = dataToEscape ?? throw new ArgumentNullException(nameof(dataToEscape));
|
||||
|
||||
// Validate that we have only one character
|
||||
if (dataToEscape.Length != 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(dataToEscape));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
char charToEscape = DataToEscape[0];
|
||||
Result = Encoding.UTF8.GetBytes(System.Uri.HexEscape(charToEscape));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class HexUnescapeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Hex char unescaped";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToUnescape { get; set; }
|
||||
|
||||
public HexUnescapeRequest(string dataToUnescape)
|
||||
{
|
||||
DataToUnescape = dataToUnescape ?? throw new ArgumentNullException(nameof(dataToUnescape));
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
if (System.Uri.IsHexEncoding(DataToUnescape, index))
|
||||
{
|
||||
Result = Encoding.UTF8.GetBytes(System.Uri.HexUnescape(DataToUnescape, ref index).ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
if (Result != null)
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class UrlDecodeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Decoded URL";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToDecode { get; set; }
|
||||
|
||||
public UrlDecodeRequest(string dataToDecode)
|
||||
{
|
||||
DataToDecode = dataToDecode ?? throw new ArgumentNullException(nameof(dataToDecode));
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
Result = Encoding.UTF8.GetBytes(HttpUtility.UrlDecode(DataToDecode));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
if (Result != null)
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Uri
|
||||
{
|
||||
public class UrlEncodeRequest : IComputeRequest
|
||||
{
|
||||
public byte[] Result { get; set; }
|
||||
|
||||
public string Description => "Encoded URL";
|
||||
|
||||
public bool IsSuccessful { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
private string DataToEncode { get; set; }
|
||||
|
||||
public UrlEncodeRequest(string dataToEncode)
|
||||
{
|
||||
DataToEncode = dataToEncode ?? throw new ArgumentNullException(nameof(dataToEncode));
|
||||
}
|
||||
|
||||
public bool Compute()
|
||||
{
|
||||
IsSuccessful = true;
|
||||
try
|
||||
{
|
||||
Result = Encoding.UTF8.GetBytes(HttpUtility.UrlEncode(DataToEncode));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(e.Message, e, GetType());
|
||||
ErrorMessage = e.Message;
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
return IsSuccessful;
|
||||
}
|
||||
|
||||
public string ResultToString()
|
||||
{
|
||||
return Encoding.UTF8.GetString(Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Text;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Base64;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.GUID;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Hashing;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Uri;
|
||||
using Wox.Plugin;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
@@ -127,6 +128,69 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new Base64DecodeRequest(content);
|
||||
}
|
||||
else if (command.StartsWith("esc:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Escape things
|
||||
if (command.Equals("esc:data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new DataEscapeRequest(content);
|
||||
}
|
||||
else if (command.Equals("esc:hex", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
|
||||
// This is only for single chars
|
||||
if (content.Length > 1)
|
||||
{
|
||||
throw new ArgumentException($"Invalid Query: {query.RawUserQuery} (To many characters.)");
|
||||
}
|
||||
else if (content.Length == 0)
|
||||
{
|
||||
throw new FormatException($"Invalid Query: {query.RawUserQuery}");
|
||||
}
|
||||
|
||||
request = new HexEscapeRequest(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException($"Invalid Query: {query.RawUserQuery}");
|
||||
}
|
||||
}
|
||||
else if (command.StartsWith("uesc:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Unescape things
|
||||
if (command.Equals("uesc:data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new DataUnescapeRequest(content);
|
||||
}
|
||||
else if (command.Equals("uesc:hex", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new HexUnescapeRequest(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException($"Invalid Query: {query.RawUserQuery}");
|
||||
}
|
||||
}
|
||||
else if (command.Equals("url", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new UrlEncodeRequest(content);
|
||||
}
|
||||
else if (command.Equals("urld", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
|
||||
string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
|
||||
request = new UrlDecodeRequest(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException($"Invalid Query: {query.RawUserQuery}");
|
||||
|
||||
@@ -93,7 +93,16 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
try
|
||||
{
|
||||
IComputeRequest computeRequest = _inputParser.ParseInput(query);
|
||||
results.Add(GetResult(computeRequest));
|
||||
var result = GetResult(computeRequest);
|
||||
|
||||
if (!string.IsNullOrEmpty(result.Title))
|
||||
{
|
||||
results.Add(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return results;
|
||||
}
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user