diff --git a/.editorconfig b/.editorconfig index 2d452a332..ef1847ca0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -111,7 +111,6 @@ dotnet_diagnostic.ca1028.severity = silent dotnet_diagnostic.ca1031.severity = silent # TODO - one at a time -dotnet_diagnostic.ca1307.severity = silent dotnet_diagnostic.ca1308.severity = silent dotnet_diagnostic.ca1508.severity = silent dotnet_diagnostic.ca1819.severity = silent diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs index 3abc83a04..3284736f3 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs @@ -220,7 +220,7 @@ namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper { continue; } - string depotKey = BitConverter.ToString(depotKeyResult.DepotKey).Replace("-", ""); + string depotKey = BitConverter.ToString(depotKeyResult.DepotKey).Replace("-", "", StringComparison.Ordinal); if (DepotKeys.TryGetValue(depotKeyResult.DepotID, out string? previousDepotKey) && (previousDepotKey == depotKey)) { continue; diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs index d88584094..431ae7168 100644 --- a/ArchiSteamFarm/ASF.cs +++ b/ArchiSteamFarm/ASF.cs @@ -19,6 +19,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using ArchiSteamFarm.RuntimeCompatibility; +using File = System.IO.File; +using Path = System.IO.Path; +#endif using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -156,11 +161,11 @@ namespace ArchiSteamFarm { if (!string.IsNullOrEmpty(Program.NetworkGroup)) { using SHA256CryptoServiceProvider hashingAlgorithm = new(); - networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Program.NetworkGroup!))).Replace("-", ""); + networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Program.NetworkGroup!))).Replace("-", "", StringComparison.Ordinal); } else if (!string.IsNullOrEmpty(globalConfig.WebProxyText)) { using SHA256CryptoServiceProvider hashingAlgorithm = new(); - networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(globalConfig.WebProxyText!))).Replace("-", ""); + networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(globalConfig.WebProxyText!))).Replace("-", "", StringComparison.Ordinal); } ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + networkGroupText).ConfigureAwait(false); diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 3efd7029e..bd69946b2 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -19,6 +19,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using ArchiSteamFarm.RuntimeCompatibility; +#endif using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -1925,7 +1928,7 @@ namespace ArchiSteamFarm { index += daysTheirVariableName.Length; text = text[index..]; - index = text.IndexOf(';'); + index = text.IndexOf(';', StringComparison.Ordinal); if (index < 0) { Bot.ArchiLogger.LogNullError(nameof(index)); @@ -2362,7 +2365,7 @@ namespace ArchiSteamFarm { return (ESteamApiKeyState.Error, null); } - if (title.Contains("Access Denied") || title.Contains("Validated email address required")) { + if (title.Contains("Access Denied", StringComparison.OrdinalIgnoreCase) || title.Contains("Validated email address required", StringComparison.OrdinalIgnoreCase)) { return (ESteamApiKeyState.AccessDenied, null); } @@ -2382,7 +2385,7 @@ namespace ArchiSteamFarm { return (ESteamApiKeyState.Error, null); } - if (text.Contains("Registering for a Steam Web API Key")) { + if (text.Contains("Registering for a Steam Web API Key", StringComparison.OrdinalIgnoreCase)) { return (ESteamApiKeyState.NotRegisteredYet, null); } diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 9f503d72d..7713258f9 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -423,7 +423,7 @@ namespace ArchiSteamFarm { return result; } - if (botName.Contains("..")) { + if (botName.Contains("..", StringComparison.Ordinal)) { string[] botRange = botName.Split(new[] { ".." }, StringSplitOptions.RemoveEmptyEntries); if (botRange.Length == 2) { @@ -1859,7 +1859,7 @@ namespace ArchiSteamFarm { throw new ArgumentNullException(nameof(message)); } - return message.Replace("\\", "\\\\").Replace("[", "\\["); + return message.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("[", "\\[", StringComparison.Ordinal); } private async Task?> GetKeysFromFile(string filePath) { @@ -3087,7 +3087,7 @@ namespace ArchiSteamFarm { string? avatarHash = null; if ((callback.AvatarHash.Length > 0) && callback.AvatarHash.Any(singleByte => singleByte != 0)) { - avatarHash = BitConverter.ToString(callback.AvatarHash).Replace("-", "").ToLowerInvariant(); + avatarHash = BitConverter.ToString(callback.AvatarHash).Replace("-", "", StringComparison.Ordinal).ToLowerInvariant(); if (string.IsNullOrEmpty(avatarHash) || avatarHash.All(singleChar => singleChar == '0')) { avatarHash = null; @@ -3489,7 +3489,7 @@ namespace ArchiSteamFarm { throw new ArgumentNullException(nameof(message)); } - return message.Replace("\\[", "[").Replace("\\\\", "\\"); + return message.Replace("\\[", "[", StringComparison.Ordinal).Replace("\\\\", "\\", StringComparison.Ordinal); } private (bool IsSteamParentalEnabled, string? SteamParentalCode) ValidateSteamParental(ParentalSettings settings, string? steamParentalCode = null) { diff --git a/ArchiSteamFarm/Commands.cs b/ArchiSteamFarm/Commands.cs index b2b1bfc9f..bfd440504 100644 --- a/ArchiSteamFarm/Commands.cs +++ b/ArchiSteamFarm/Commands.cs @@ -595,7 +595,7 @@ namespace ArchiSteamFarm { uint gameID; string type; - int index = entry.IndexOf('/'); + int index = entry.IndexOf('/', StringComparison.Ordinal); if ((index > 0) && (entry.Length > index + 1)) { if (!uint.TryParse(entry[(index + 1)..], out gameID) || (gameID == 0)) { @@ -2049,7 +2049,7 @@ namespace ArchiSteamFarm { string game; string type; - int index = entry.IndexOf('/'); + int index = entry.IndexOf('/', StringComparison.Ordinal); if ((index > 0) && (entry.Length > index + 1)) { game = entry[(index + 1)..]; diff --git a/ArchiSteamFarm/IPC/WebUtilities.cs b/ArchiSteamFarm/IPC/WebUtilities.cs index 4b65cfc8e..742718bd0 100644 --- a/ArchiSteamFarm/IPC/WebUtilities.cs +++ b/ArchiSteamFarm/IPC/WebUtilities.cs @@ -19,6 +19,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using ArchiSteamFarm.RuntimeCompatibility; +#endif using System; using System.Linq; using System.Net; @@ -58,7 +61,7 @@ namespace ArchiSteamFarm.IPC { } // We can try one more time by trying to smartly guess the assembly name from the namespace, this will work for custom libraries like SteamKit2 - int index = typeText.IndexOf('.'); + int index = typeText.IndexOf('.', StringComparison.Ordinal); if ((index <= 0) || (index >= typeText.Length - 1)) { return null; diff --git a/ArchiSteamFarm/OS.cs b/ArchiSteamFarm/OS.cs index e79a65954..27673698c 100644 --- a/ArchiSteamFarm/OS.cs +++ b/ArchiSteamFarm/OS.cs @@ -106,7 +106,7 @@ namespace ArchiSteamFarm { // At the same time it'd be the best if we avoided all special characters, such as '/' found e.g. in base64, as we can't be sure that it's not a prohibited character in regards to native OS implementation // Because of that, SHA256 is sufficient for our case, as it generates alphanumeric characters only, and is barely 256-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing algorithm will do, and the shorter the better using (SHA256CryptoServiceProvider hashingAlgorithm = new()) { - uniqueName = "Global\\" + GetOsResourceName(nameof(SingleInstance)) + "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()))).Replace("-", ""); + uniqueName = "Global\\" + GetOsResourceName(nameof(SingleInstance)) + "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()))).Replace("-", "", StringComparison.Ordinal); } Mutex? singleInstance = null; diff --git a/ArchiSteamFarm/RuntimeCompatibility/StaticHelpers.cs b/ArchiSteamFarm/RuntimeCompatibility/StaticHelpers.cs index c6f20b98e..034325da9 100644 --- a/ArchiSteamFarm/RuntimeCompatibility/StaticHelpers.cs +++ b/ArchiSteamFarm/RuntimeCompatibility/StaticHelpers.cs @@ -21,11 +21,13 @@ #if NETFRAMEWORK using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Net.WebSockets; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; +using ArchiSteamFarm.Localization; using Microsoft.AspNetCore.Hosting; #endif using System; @@ -102,6 +104,14 @@ namespace ArchiSteamFarm.RuntimeCompatibility { return default(ValueTask); } + public static int IndexOf(this string source, char value, StringComparison comparisonType) { + if (source == null) { + throw new ArgumentNullException(nameof(source)); + } + + return source.IndexOf(value.ToString(), comparisonType); + } + public static async Task ReceiveAsync(this WebSocket webSocket, byte[] buffer, CancellationToken cancellationToken) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); @@ -110,6 +120,43 @@ namespace ArchiSteamFarm.RuntimeCompatibility { return await webSocket.ReceiveAsync(new ArraySegment(buffer), cancellationToken).ConfigureAwait(false); } + public static string Replace(this string source, string oldValue, string? newValue, StringComparison comparisonType) { + if (source == null) { + throw new ArgumentNullException(nameof(source)); + } + + if (oldValue == null) { + throw new ArgumentNullException(nameof(oldValue)); + } + + if (oldValue.Length == 0) { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(oldValue)), nameof(oldValue)); + } + + int startIndex = 0; + + while (true) { + if (source.Length == 0) { + return source; + } + + int index = source.IndexOf(oldValue, startIndex, comparisonType); + + if (index < 0) { + return source; + } + + startIndex = index; + + source = source.Remove(index, oldValue.Length); + + if (!string.IsNullOrEmpty(newValue)) { + source = source.Insert(index, newValue!); + startIndex += newValue!.Length; + } + } + } + public static async Task SendAsync(this WebSocket webSocket, byte[] buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket));