diff --git a/.gitignore b/.gitignore index 584fc7c3..e370b7cc 100644 --- a/.gitignore +++ b/.gitignore @@ -331,4 +331,5 @@ ASALocalRun/ # VS Code User Files -.vscode/ \ No newline at end of file +.vscode/ +.sonarlint/ diff --git a/.sonarlint/FASTER.slconfig b/.sonarlint/FASTER.slconfig deleted file mode 100644 index 12a5d18d..00000000 --- a/.sonarlint/FASTER.slconfig +++ /dev/null @@ -1,15 +0,0 @@ -{ - "ServerUri": "https://sonarcloud.io/", - "Organization": { - "Key": "foxlicorp", - "Name": "Keelah" - }, - "ProjectKey": "Foxlider_FASTER", - "ProjectName": "FASTER", - "Profiles": { - "CSharp": { - "ProfileKey": "AW7Rfkrd6A1-kc3fchk2", - "ProfileTimestamp": "2021-11-28T14:54:48Z" - } - } -} \ No newline at end of file diff --git a/.sonarlint/foxlider_faster/CSharp/SonarLint.xml b/.sonarlint/foxlider_faster/CSharp/SonarLint.xml deleted file mode 100644 index ffa3aa13..00000000 --- a/.sonarlint/foxlider_faster/CSharp/SonarLint.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - sonar.cs.analyzeGeneratedCode - false - - - sonar.cs.file.suffixes - .cs - - - sonar.cs.ignoreHeaderComments - true - - - sonar.cs.roslyn.ignoreIssues - false - - - - - S107 - - - max - 7 - - - - - S110 - - - max - 5 - - - - - S1479 - - - maximum - 30 - - - - - S2342 - - - flagsAttributeFormat - ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$ - - - format - ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$ - - - - - S2436 - - - max - 2 - - - maxMethod - 3 - - - - - S3776 - - - propertyThreshold - 3 - - - threshold - 25 - - - - - \ No newline at end of file diff --git a/.sonarlint/foxlider_fastercsharp.ruleset b/.sonarlint/foxlider_fastercsharp.ruleset deleted file mode 100644 index 19d72398..00000000 --- a/.sonarlint/foxlider_fastercsharp.ruleset +++ /dev/null @@ -1,368 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/FASTER/FASTER.csproj b/FASTER/FASTER.csproj index 9e911826..410d5f9c 100644 --- a/FASTER/FASTER.csproj +++ b/FASTER/FASTER.csproj @@ -7,7 +7,7 @@ win-x64 true true - 1.8.6.1 + 1.8.7.1 Keelah Fox FoxliCorp. Fox's Arma Server Tool Extended Rewrite @@ -51,17 +51,17 @@ - - + + - - - - + + + + diff --git a/FASTER/MainWindow.xaml.cs b/FASTER/MainWindow.xaml.cs index b2d5f0db..0b24bde7 100644 --- a/FASTER/MainWindow.xaml.cs +++ b/FASTER/MainWindow.xaml.cs @@ -218,6 +218,9 @@ private void ToggleButton_Click(object sender, RoutedEventArgs e) default: if (IServerProfilesMenu.Items.Cast().FirstOrDefault(p => p.Name == nav.Name) != null) { + var profile = new Profile(); + MainContent.Content = profile; + ContentProfile.DataContext = ContentProfileViews.First(p => p.Profile.Id == nav.Name); ContentProfile.Refresh(); MainContent.Content = ContentProfile; diff --git a/FASTER/Models/SteamWebApi.cs b/FASTER/Models/SteamWebApi.cs index bda808e2..330fb915 100644 --- a/FASTER/Models/SteamWebApi.cs +++ b/FASTER/Models/SteamWebApi.cs @@ -1,11 +1,16 @@ using BytexDigital.Steam.Core; +using MahApps.Metro.Controls.Dialogs; + using Newtonsoft.Json.Linq; using System; using System.Diagnostics; +using System.IO; using System.Net; using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; using System.Windows; namespace FASTER.Models @@ -94,29 +99,112 @@ private static string GetApiKey() } } - internal class AuthCodeProvider : SteamAuthenticationCodesProvider + internal class AuthCodeProvider : SteamAuthenticator { - public override string GetEmailAuthenticationCode(SteamCredentials steamCredentials) + + private readonly string _persistenceDirectory; + private readonly string _uniqueStorageName; + public string AccessToken { get; protected set; } + public string GuardData { get; protected set; } + + + public AuthCodeProvider(string uniqueStorageName, string persistenceDirectory) + { + _uniqueStorageName = uniqueStorageName; + _persistenceDirectory = persistenceDirectory; + } + + public override Task GetEmailAuthenticationCodeAsync(string accountEmail, bool previousCodeWasIncorrect, CancellationToken cancellationToken = default) { - MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nPlease enter your email auth code: "; + if (previousCodeWasIncorrect) + MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nPreviously entered email code was incorrect!"; + + MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nPlease enter your 2FA code: "; var input = MainWindow.Instance.SteamUpdaterViewModel.SteamGuardInput().Result; MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nRetrying... "; - return input; + return Task.FromResult(input); } - public override string GetTwoFactorAuthenticationCode(SteamCredentials steamCredentials) + public override Task GetTwoFactorAuthenticationCodeAsync(bool previousCodeWasIncorrect, CancellationToken cancellationToken = default) { + if (previousCodeWasIncorrect) + MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nPreviously entered 2FA code was incorrect!"; + + MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nPlease enter your 2FA code: "; var input = MainWindow.Instance.SteamUpdaterViewModel.SteamGuardInput().Result; MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nRetrying... "; - return input; + return Task.FromResult(input); + } + + public override Task NotifyMobileNotificationAsync(CancellationToken cancellationToken = default) + { + MainWindow.Instance.SteamUpdaterViewModel.Parameters.Output += "\nMobile notification sent. Answer \"y\" once you've authorized this login. If no notification was received or you'd like to enter a traditional 2FA code, enter \"n\": "; + + MessageDialogResult response; + + do + { + response = MainWindow.Instance.SteamUpdaterViewModel.SteamGuardInputPhone().Result; + } while (response != MessageDialogResult.Affirmative); + + return Task.FromResult(true); + } + + public override Task PersistAccessTokenAsync(string token, CancellationToken cancellationToken = default) + { + AccessToken = token; + + if (string.IsNullOrEmpty(_persistenceDirectory)) return Task.CompletedTask; + + Directory.CreateDirectory(_persistenceDirectory); + File.WriteAllText(Path.Combine(_persistenceDirectory, $"{_uniqueStorageName}_accesstoken"), AccessToken); + + return Task.CompletedTask; + } + + + public override Task GetAccessTokenAsync(CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(_persistenceDirectory)) + { + return Task.FromResult(AccessToken); + } + + var path = Path.Combine(_persistenceDirectory, $"{_uniqueStorageName}_accesstoken"); + + return Task.FromResult(File.Exists(path) ? File.ReadAllText(path) : AccessToken); + } + + public override Task PersistGuardDataAsync(string data, CancellationToken cancellationToken = default) + { + GuardData = data; + + if (string.IsNullOrEmpty(_persistenceDirectory)) return Task.CompletedTask; + + Directory.CreateDirectory(_persistenceDirectory); + File.WriteAllText(Path.Combine(_persistenceDirectory, $"{_uniqueStorageName}_guarddata"), GuardData); + + return Task.CompletedTask; + } + + public override Task GetGuardDataAsync(CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(_persistenceDirectory)) + { + return Task.FromResult(GuardData); + } + + var path = Path.Combine(_persistenceDirectory, $"{_uniqueStorageName}_guarddata"); + + return Task.FromResult(File.Exists(path) ? File.ReadAllText(path) : GuardData); } } diff --git a/FASTER/ViewModel/SteamUpdaterViewModel.cs b/FASTER/ViewModel/SteamUpdaterViewModel.cs index 2dcb1e50..f64ea72f 100644 --- a/FASTER/ViewModel/SteamUpdaterViewModel.cs +++ b/FASTER/ViewModel/SteamUpdaterViewModel.cs @@ -3,7 +3,6 @@ using BytexDigital.Steam.ContentDelivery.Models; using BytexDigital.Steam.ContentDelivery.Models.Downloading; using BytexDigital.Steam.Core; -using BytexDigital.Steam.Core.Enumerations; using BytexDigital.Steam.Core.Structs; using FASTER.Models; @@ -113,7 +112,6 @@ public bool IsDlOverride internal SteamClient SteamClient; internal SteamContentClient SteamContentClient; - private SteamCredentials _steamCredentials; public void PasswordChanged(string password) { @@ -293,20 +291,18 @@ internal async Task RunServerUpdater(string path, uint appId, List<(uint id if (!await SteamLogin()) return UpdateState.LoginFailed; - var _OS = SteamClient?.GetSteamOs().Identifier; Stopwatch sw = Stopwatch.StartNew(); foreach (var depot in depots) { try { - SteamOs steamOs = new(_OS); ManifestId manifestId; + manifestId = await SteamContentClient.GetDepotManifestIdAsync(appId, depot.id, depot.branch, depot.pass); - manifestId = await SteamContentClient.GetDepotDefaultManifestIdAsync(appId, depot.id, depot.branch, depot.pass); + Parameters.Output += $"\nFetching infor;ations of app {appId}, depot {depot.id} from Steam ({depots.IndexOf(depot)+1}/{depots.Count})... "; + var downloadHandler = await SteamContentClient.GetAppDataAsync(appId, depot.id, manifestId, tokenSource.Token); - Parameters.Output += $"\nAttempting to start download of app {appId}, depot {depot.id} ({depots.IndexOf(depot)+1}/{depots.Count})... "; - var downloadHandler = await SteamContentClient.GetAppDataAsync(appId, depot.id, manifestId, depot.branch, depot.pass, steamOs); await Download(downloadHandler, path); } catch (Exception ex) @@ -341,12 +337,10 @@ public async Task RunModUpdater(ulong modId, string path) return UpdateState.LoginFailed; } - var _OS = SteamClient.GetSteamOs().Identifier; Stopwatch sw = Stopwatch.StartNew(); try { - SteamOs steamOs = new(_OS); ManifestId manifestId = default; Parameters.Output += $"\nFetching mod {modId} infos... "; @@ -361,12 +355,7 @@ public async Task RunModUpdater(ulong modId, string path) Parameters.Output += $"\nAttempting to start download of item {modId}... "; - var downloadHandler = await SteamContentClient.GetPublishedFileDataAsync( - modId, - manifestId, - null, - null, - steamOs); + var downloadHandler = await SteamContentClient.GetPublishedFileDataAsync(modId, manifestId, tokenSource.Token); await Download(downloadHandler, path); } @@ -404,8 +393,6 @@ public async Task RunModsUpdater(ObservableCollection mods) return UpdateState.LoginFailed; } - var _OS = SteamClient.GetSteamOs().Identifier; - Parameters.Output += "\nAdding mods to download list..."; SemaphoreSlim maxThread = new(1); @@ -432,7 +419,6 @@ public async Task RunModsUpdater(ObservableCollection mods) Stopwatch sw = Stopwatch.StartNew(); try { - SteamOs steamOs = new(_OS); ManifestId manifestId = default; if(mod.LocalLastUpdated > mod.SteamLastUpdated) @@ -453,11 +439,7 @@ public async Task RunModsUpdater(ObservableCollection mods) Parameters.Output += $"\n Attempting to start download of item {mod.WorkshopId}... "; - var downloadHandler = SteamContentClient.GetPublishedFileDataAsync(mod.WorkshopId, - manifestId, - null, - null, - steamOs); + var downloadHandler = SteamContentClient.GetPublishedFileDataAsync(mod.WorkshopId, manifestId, tokenSource.Token); DownloadForMultiple(downloadHandler.Result, mod.Path).Wait(); } catch (TaskCanceledException) @@ -505,11 +487,10 @@ internal async Task SteamLogin() { IsLoggingIn = true; var path = Path.Combine(Path.GetDirectoryName(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath) ?? string.Empty, "sentries"); - SteamAuthenticationFilesProvider sentryFileProvider = new DirectorySteamAuthenticationFilesProvider(path); - if (_steamCredentials == null || _steamCredentials.IsAnonymous) - _steamCredentials = new SteamCredentials(Parameters.Username, Encryption.Instance.DecryptData(Parameters.Password), Parameters.ApiKey); - SteamClient ??= new SteamClient(_steamCredentials, new AuthCodeProvider(), sentryFileProvider); + SteamCredentials _steamCredentials = new SteamCredentials(Parameters.Username, Encryption.Instance.DecryptData(Parameters.Password), Parameters.ApiKey); + + SteamClient ??= new SteamClient(_steamCredentials, new AuthCodeProvider(_steamCredentials.Username, path)); if (!SteamClient.IsConnected || SteamClient.IsFaulted) { @@ -694,6 +675,9 @@ private async Task DownloadForMultiple(IDownloadHandler downloadHandler, string public async Task SteamGuardInput() { return await DialogCoordinator.ShowInputAsync(this, "Steam Guard", "Please enter your 2FA code"); } + public async Task SteamGuardInputPhone() + { return await DialogCoordinator.ShowMessageAsync(this, "Steam Guard", "Press OK after accepting authentification on mobile", MessageDialogStyle.Affirmative); } + public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) diff --git a/FASTER_Version.xml b/FASTER_Version.xml index ed1c7076..82ee33d4 100644 --- a/FASTER_Version.xml +++ b/FASTER_Version.xml @@ -1,6 +1,6 @@  - 1.8.6.1 + 1.8.7.1 https://github.com/Foxlider/FASTER/releases/latest/download/Release_x64.zip https://github.com/Foxlider/FASTER/releases true