InputParser.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System;
  6  using System.Security.Cryptography;
  7  using System.Text;
  8  
  9  using Community.PowerToys.Run.Plugin.ValueGenerator.Base64;
 10  using Community.PowerToys.Run.Plugin.ValueGenerator.GUID;
 11  using Community.PowerToys.Run.Plugin.ValueGenerator.Hashing;
 12  using Community.PowerToys.Run.Plugin.ValueGenerator.Uri;
 13  using Wox.Plugin;
 14  using Wox.Plugin.Logger;
 15  
 16  namespace Community.PowerToys.Run.Plugin.ValueGenerator
 17  {
 18      public class InputParser
 19      {
 20          public IComputeRequest ParseInput(Query query)
 21          {
 22              IComputeRequest request;
 23  
 24              if (query.Terms.Count == 0)
 25              {
 26                  throw new FormatException("Empty request");
 27              }
 28  
 29              string command = query.Terms[0];
 30  
 31              if (command.Equals("md5", StringComparison.OrdinalIgnoreCase))
 32              {
 33                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
 34                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
 35  
 36                  if (content == string.Empty)
 37                  {
 38                      throw new FormatException("Empty hash request");
 39                  }
 40  
 41                  Log.Debug($"Will calculate MD5 hash for: {content}", GetType());
 42                  request = new HashRequest(HashAlgorithmName.MD5, Encoding.UTF8.GetBytes(content));
 43              }
 44              else if (command.StartsWith("sha", StringComparison.InvariantCultureIgnoreCase))
 45              {
 46                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
 47                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
 48                  HashAlgorithmName algorithmName;
 49  
 50                  switch (command.Substring(3))
 51                  {
 52                      case "1":
 53                          algorithmName = HashAlgorithmName.SHA1;
 54                          break;
 55  
 56                      case "256":
 57                          algorithmName = HashAlgorithmName.SHA256;
 58                          break;
 59  
 60                      case "384":
 61                          algorithmName = HashAlgorithmName.SHA384;
 62                          break;
 63  
 64                      case "512":
 65                          algorithmName = HashAlgorithmName.SHA512;
 66                          break;
 67                      default:
 68                          throw new FormatException("Unknown SHA variant. Supported variants: SHA1, SHA256, SHA384, SHA512");
 69                  }
 70  
 71                  if (content == string.Empty)
 72                  {
 73                      throw new FormatException("Empty hash request");
 74                  }
 75  
 76                  Log.Debug($"Will calculate {algorithmName} hash for: {content}", GetType());
 77                  request = new HashRequest(algorithmName, Encoding.UTF8.GetBytes(content));
 78              }
 79              else if (command.StartsWith("guid", StringComparison.InvariantCultureIgnoreCase) ||
 80                       command.StartsWith("uuid", StringComparison.InvariantCultureIgnoreCase))
 81              {
 82                  string content = query.Search.Substring(command.Length).Trim();
 83  
 84                  // Default to version 4
 85                  int version = 4;
 86                  string versionQuery = command.Substring(4);
 87  
 88                  if (versionQuery.Length > 0)
 89                  {
 90                      if (versionQuery.StartsWith("v", StringComparison.InvariantCultureIgnoreCase))
 91                      {
 92                          versionQuery = versionQuery.Substring(1);
 93                      }
 94  
 95                      if (!int.TryParse(versionQuery, null, out version))
 96                      {
 97                          throw new FormatException("Could not determine requested GUID version. Supported versions are 1, 3, 4, 5, and 7");
 98                      }
 99                  }
100  
101                  if (version == 3 || version == 5)
102                  {
103                      string[] sParameters = content.Split(" ");
104  
105                      if (sParameters.Length != 2)
106                      {
107                          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>");
108                      }
109  
110                      string namespaceParameter = sParameters[0];
111                      string nameParameter = sParameters[1];
112  
113                      request = new GUIDRequest(version, namespaceParameter, nameParameter);
114                  }
115                  else
116                  {
117                      request = new GUIDRequest(version);
118                  }
119              }
120              else if (command.Equals("base64", StringComparison.OrdinalIgnoreCase))
121              {
122                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
123                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
124                  request = new Base64Request(Encoding.UTF8.GetBytes(content));
125              }
126              else if (command.Equals("base64d", StringComparison.OrdinalIgnoreCase))
127              {
128                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
129                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
130                  request = new Base64DecodeRequest(content);
131              }
132              else if (command.StartsWith("esc:", StringComparison.OrdinalIgnoreCase))
133              {
134                  // Escape things
135                  if (command.Equals("esc:data", StringComparison.OrdinalIgnoreCase))
136                  {
137                      int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
138                      string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
139                      request = new DataEscapeRequest(content);
140                  }
141                  else if (command.Equals("esc:hex", StringComparison.OrdinalIgnoreCase))
142                  {
143                      int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
144                      string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
145  
146                      // This is only for single chars
147                      if (content.Length > 1)
148                      {
149                          throw new ArgumentException($"Invalid Query: {query.RawUserQuery} (Too many characters.)");
150                      }
151                      else if (content.Length == 0)
152                      {
153                          throw new FormatException($"Invalid Query: {query.RawUserQuery}");
154                      }
155  
156                      request = new HexEscapeRequest(content);
157                  }
158                  else
159                  {
160                      throw new FormatException($"Invalid Query: {query.RawUserQuery}");
161                  }
162              }
163              else if (command.StartsWith("uesc:", StringComparison.OrdinalIgnoreCase))
164              {
165                  // Unescape things
166                  if (command.Equals("uesc:data", StringComparison.OrdinalIgnoreCase))
167                  {
168                      int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
169                      string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
170                      request = new DataUnescapeRequest(content);
171                  }
172                  else if (command.Equals("uesc:hex", StringComparison.OrdinalIgnoreCase))
173                  {
174                      int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
175                      string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
176                      request = new HexUnescapeRequest(content);
177                  }
178                  else
179                  {
180                      throw new FormatException($"Invalid Query: {query.RawUserQuery}");
181                  }
182              }
183              else if (command.Equals("url", StringComparison.OrdinalIgnoreCase))
184              {
185                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
186                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
187                  request = new UrlEncodeRequest(content);
188              }
189              else if (command.Equals("urld", StringComparison.OrdinalIgnoreCase))
190              {
191                  int commandIndex = query.RawUserQuery.IndexOf(command, StringComparison.InvariantCultureIgnoreCase);
192                  string content = query.RawUserQuery.Substring(commandIndex + command.Length).Trim();
193                  request = new UrlDecodeRequest(content);
194              }
195              else
196              {
197                  throw new FormatException($"Invalid Query: {query.RawUserQuery}");
198              }
199  
200              return request;
201          }
202      }
203  }