2023-07-18 10:44:02 +01:00
// 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.Cryptography ;
using System.Text ;
2024-09-16 16:09:43 -04:00
2023-07-18 10:44:02 +01:00
using Community.PowerToys.Run.Plugin.ValueGenerator.Base64 ;
using Community.PowerToys.Run.Plugin.ValueGenerator.GUID ;
using Community.PowerToys.Run.Plugin.ValueGenerator.Hashing ;
2024-01-03 17:30:11 +01:00
using Community.PowerToys.Run.Plugin.ValueGenerator.Uri ;
2023-07-18 10:44:02 +01:00
using Wox.Plugin ;
using Wox.Plugin.Logger ;
namespace Community.PowerToys.Run.Plugin.ValueGenerator
{
public class InputParser
{
public IComputeRequest ParseInput ( Query query )
{
IComputeRequest request ;
if ( query . Terms . Count = = 0 )
{
throw new FormatException ( "Empty request" ) ;
}
string command = query . Terms [ 0 ] ;
2023-12-28 13:37:13 +03:00
if ( command . Equals ( "md5" , StringComparison . OrdinalIgnoreCase ) )
2023-07-18 10:44:02 +01:00
{
int commandIndex = query . RawUserQuery . IndexOf ( command , StringComparison . InvariantCultureIgnoreCase ) ;
string content = query . RawUserQuery . Substring ( commandIndex + command . Length ) . Trim ( ) ;
if ( content = = string . Empty )
{
throw new FormatException ( "Empty hash request" ) ;
}
Log . Debug ( $"Will calculate MD5 hash for: {content}" , GetType ( ) ) ;
request = new HashRequest ( HashAlgorithmName . MD5 , Encoding . UTF8 . GetBytes ( content ) ) ;
}
else if ( command . StartsWith ( "sha" , StringComparison . InvariantCultureIgnoreCase ) )
{
int commandIndex = query . RawUserQuery . IndexOf ( command , StringComparison . InvariantCultureIgnoreCase ) ;
string content = query . RawUserQuery . Substring ( commandIndex + command . Length ) . Trim ( ) ;
HashAlgorithmName algorithmName ;
switch ( command . Substring ( 3 ) )
{
case "1" :
algorithmName = HashAlgorithmName . SHA1 ;
break ;
case "256" :
algorithmName = HashAlgorithmName . SHA256 ;
break ;
case "384" :
algorithmName = HashAlgorithmName . SHA384 ;
break ;
case "512" :
algorithmName = HashAlgorithmName . SHA512 ;
break ;
default :
2024-07-23 00:31:32 +09:00
throw new FormatException ( "Unknown SHA variant. Supported variants: SHA1, SHA256, SHA384, SHA512" ) ;
2023-07-18 10:44:02 +01:00
}
if ( content = = string . Empty )
{
throw new FormatException ( "Empty hash request" ) ;
}
Log . Debug ( $"Will calculate {algorithmName} hash for: {content}" , GetType ( ) ) ;
request = new HashRequest ( algorithmName , Encoding . UTF8 . GetBytes ( content ) ) ;
}
else if ( command . StartsWith ( "guid" , StringComparison . InvariantCultureIgnoreCase ) | |
command . StartsWith ( "uuid" , StringComparison . InvariantCultureIgnoreCase ) )
{
string content = query . Search . Substring ( command . Length ) . Trim ( ) ;
// Default to version 4
int version = 4 ;
string versionQuery = command . Substring ( 4 ) ;
if ( versionQuery . Length > 0 )
{
if ( versionQuery . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase ) )
{
versionQuery = versionQuery . Substring ( 1 ) ;
}
if ( ! int . TryParse ( versionQuery , null , out version ) )
{
2024-11-28 16:52:16 +01:00
throw new FormatException ( "Could not determine requested GUID version. Supported versions are 1, 3, 4, 5, and 7" ) ;
2023-07-18 10:44:02 +01:00
}
}
if ( version = = 3 | | version = = 5 )
{
string [ ] sParameters = content . Split ( " " ) ;
if ( sParameters . Length ! = 2 )
{
2024-07-23 00:31:32 +09:00
throw new ArgumentException ( $"GUID version {version} require 2 parameters - a namespace GUID and a name.\nExample: uuidv{version} ns:<DNS, URL, OID, or X500> <your input>" ) ;
2023-07-18 10:44:02 +01:00
}
string namespaceParameter = sParameters [ 0 ] ;
string nameParameter = sParameters [ 1 ] ;
request = new GUIDRequest ( version , namespaceParameter , nameParameter ) ;
}
else
{
request = new GUIDRequest ( version ) ;
}
}
2023-12-28 13:37:13 +03:00
else if ( command . Equals ( "base64" , StringComparison . OrdinalIgnoreCase ) )
2023-07-18 10:44:02 +01:00
{
int commandIndex = query . RawUserQuery . IndexOf ( command , StringComparison . InvariantCultureIgnoreCase ) ;
string content = query . RawUserQuery . Substring ( commandIndex + command . Length ) . Trim ( ) ;
request = new Base64Request ( Encoding . UTF8 . GetBytes ( content ) ) ;
}
2023-12-28 13:37:13 +03:00
else if ( command . Equals ( "base64d" , StringComparison . OrdinalIgnoreCase ) )
2023-08-21 12:05:08 +02:00
{
int commandIndex = query . RawUserQuery . IndexOf ( command , StringComparison . InvariantCultureIgnoreCase ) ;
string content = query . RawUserQuery . Substring ( commandIndex + command . Length ) . Trim ( ) ;
request = new Base64DecodeRequest ( content ) ;
}
2024-01-03 17:30:11 +01:00
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 )
{
2025-01-19 15:31:13 +00:00
throw new ArgumentException ( $"Invalid Query: {query.RawUserQuery} (Too many characters.)" ) ;
2024-01-03 17:30:11 +01:00
}
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 ) ;
}
2023-07-18 10:44:02 +01:00
else
{
throw new FormatException ( $"Invalid Query: {query.RawUserQuery}" ) ;
}
return request ;
}
}
}