From 63630e6a61cf49570f6c0c829aaf0f2aaa9d2781 Mon Sep 17 00:00:00 2001 From: MaxIsJoe <34368774+MaxIsJoe@users.noreply.github.com> Date: Sat, 5 Jul 2025 02:17:00 +0300 Subject: [PATCH 1/3] Add the option to disable codescan --- .../Models/ConfigFile/Preferences.cs | 7 ++ .../Services/CodeScanConfigService.cs | 6 +- .../Services/InstallationService.cs | 103 ++++++++++++++---- .../Services/Interface/IServerService.cs | 8 ++ .../ViewModels/PreferencesPanelViewModel.cs | 35 ++++++ .../Views/PreferencesPanelView.xaml | 5 + 6 files changed, 139 insertions(+), 25 deletions(-) diff --git a/UnitystationLauncher/Models/ConfigFile/Preferences.cs b/UnitystationLauncher/Models/ConfigFile/Preferences.cs index 570363e..1377a62 100644 --- a/UnitystationLauncher/Models/ConfigFile/Preferences.cs +++ b/UnitystationLauncher/Models/ConfigFile/Preferences.cs @@ -8,6 +8,7 @@ public class Preferences : ReactiveObject private int _ignoreVersionUpdate; private string _installationPath = string.Empty; private bool? _TTSEnabled = null; + private bool? _allowCodeScan = true; public bool AutoRemove { @@ -32,4 +33,10 @@ public bool? TTSEnabled get => _TTSEnabled; set => this.RaiseAndSetIfChanged(ref _TTSEnabled, value); } + + public bool? AllowCodeScan + { + get => _allowCodeScan; + set => this.RaiseAndSetIfChanged(ref _allowCodeScan, value); + } } diff --git a/UnitystationLauncher/Services/CodeScanConfigService.cs b/UnitystationLauncher/Services/CodeScanConfigService.cs index 8078c3e..d234507 100644 --- a/UnitystationLauncher/Services/CodeScanConfigService.cs +++ b/UnitystationLauncher/Services/CodeScanConfigService.cs @@ -46,7 +46,7 @@ public CodeScanConfigService(HttpClient httpClient, IPreferencesService preferen } string pathBase = _preferencesService.GetPreferences().InstallationPath; - string folderName = GetFolderName(version); + string folderName = GetFolderName(version, _environmentService); string versionPath = Path.Combine(pathBase, "nonbuild", version, folderName); if (Directory.Exists(versionPath) == false) @@ -194,9 +194,9 @@ private string GetZipFolderName() } } - private string GetFolderName(string version) + public static string GetFolderName(string version, IEnvironmentService environmentService) { - CurrentEnvironment os = _environmentService.GetCurrentEnvironment(); + CurrentEnvironment os = environmentService.GetCurrentEnvironment(); switch (os) { case CurrentEnvironment.WindowsStandalone: diff --git a/UnitystationLauncher/Services/InstallationService.cs b/UnitystationLauncher/Services/InstallationService.cs index befb863..81d5f57 100644 --- a/UnitystationLauncher/Services/InstallationService.cs +++ b/UnitystationLauncher/Services/InstallationService.cs @@ -95,16 +95,22 @@ public List GetInstallations() return (null!, failureReason); } - bool result = await _codeScanConfigService.ValidGoodFilesVersionAsync(server.GoodFileVersion); + if (_preferencesService.GetPreferences().AllowCodeScan is true) + { + bool result = await _codeScanConfigService.ValidGoodFilesVersionAsync(server.GoodFileVersion); - if (result == false) + if (result == false) + { + const string failureReason = "server does not have a valid ServerGoodFileVersion "; + Log.Warning(failureReason + $" ServerName: {server.ServerName} ServerGoodFileVersion : {server.GoodFileVersion}"); + return (null!, failureReason); + } + } + else { - const string failureReason = "server does not have a valid ServerGoodFileVersion "; - Log.Warning(failureReason + $" ServerName: {server.ServerName} ServerGoodFileVersion : {server.GoodFileVersion}"); - return (null!, failureReason); + Log.Information("Code scan is disabled, skipping..."); } - Download? download = GetInProgressDownload(server.ForkName, server.BuildVersion); if (download != null) @@ -168,6 +174,7 @@ public List GetInstallations() { const string failureReason = "Couldn't find executable to start."; Log.Warning(failureReason + $" Installation Path: {installation.InstallationPath ?? "null"}"); + _ = ShowErrorWhenNoServerExecutable(installationId, server); return (false, failureReason); } @@ -195,6 +202,30 @@ public List GetInstallations() return (true, string.Empty); } + private async Task ShowErrorWhenNoServerExecutable(Guid installationId, string? server) + { + if (server is "") return; + IMsBox msgBox = MessageBoxBuilder.CreateMessageBox( + MessageBoxButtons.YesNo, + "Executable Not Found", + "The executable for this installation could not be found. Would you like to re-download it?" + ); + string response = await msgBox.ShowAsync(); + if (response.Equals(MessageBoxResults.Yes)) + { + DeleteInstallation(installationId); + Server? serverDetails = await _serverService.GetServerByIpAddress(server); + if (serverDetails != null) + { + _ = DownloadInstallationAsync(serverDetails); + } + } + else + { + DeleteInstallation(installationId); + } + } + public (bool, string) DeleteInstallation(Guid installationId) { Installation? installation = GetInstallationById(installationId); @@ -460,7 +491,14 @@ private async Task StartDownloadAsync(Download download) // ExtractAndScan() must be run in a separate thread, but we want this one to wait for that one to finish // Without this download progress will not work properly - await Task.Run(() => ExtractAndScan(download, progressStream)); + if (_preferencesService.GetPreferences().AllowCodeScan is false) + { + await Task.Run(() => Extract(download, progressStream)); + } + else + { + await Task.Run(() => ExtractAndScan(download, progressStream)); + } } catch (Exception e) { @@ -474,6 +512,22 @@ private async Task StartDownloadAsync(Download download) } } + private async Task Extract(Download download, ProgressStream progressStream) + { + try + { + ZipArchive archive = new(progressStream); + Log.Information($"Extracting without scan to: {download.InstallPath}"); + archive.ExtractToDirectory(download.InstallPath, true); + InstallationDone(download); + } + catch (Exception e) + { + Log.Information($"Extracting stopped with {e}"); + download.DownloadState = DownloadState.Failed; + } + } + private async Task ExtractAndScan(Download download, ProgressStream progressStream) { List scanLogs = []; @@ -498,26 +552,13 @@ void ScanLogs(ScanLog log) scanLogs.Add(log); } - + download.DownloadState = DownloadState.Scanning; bool scanTask = await _codeScanService.OnScanAsync(archive, download.InstallPath, download.GoodFileVersion, ScanLogs); if (scanTask) { - Log.Information("Download completed"); - - _installations.Add(new() - { - BuildVersion = download.BuildVersion, - ForkName = download.ForkName, - InstallationId = Guid.NewGuid(), - InstallationPath = download.InstallPath, - LastPlayedDate = DateTime.Now - }); - - WriteInstallations(); - EnsureExecutableFlagOnUnixSystems(download.InstallPath); - download.DownloadState = DownloadState.Installed; + InstallationDone(download); } else { @@ -553,6 +594,24 @@ void ScanLogs(ScanLog log) } } + private void InstallationDone(Download download) + { + Log.Information("Download completed"); + + _installations.Add(new() + { + BuildVersion = download.BuildVersion, + ForkName = download.ForkName, + InstallationId = Guid.NewGuid(), + InstallationPath = download.InstallPath, + LastPlayedDate = DateTime.Now + }); + + WriteInstallations(); + EnsureExecutableFlagOnUnixSystems(download.InstallPath); + download.DownloadState = DownloadState.Installed; + } + private static async Task ShowScanFailPopUp(string message, string logFolder) { IMsBox msgBox = MessageBoxBuilder.CreateMessageBox( diff --git a/UnitystationLauncher/Services/Interface/IServerService.cs b/UnitystationLauncher/Services/Interface/IServerService.cs index 6fe87f0..8ad3f1d 100644 --- a/UnitystationLauncher/Services/Interface/IServerService.cs +++ b/UnitystationLauncher/Services/Interface/IServerService.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using UnitystationLauncher.Models; using UnitystationLauncher.Models.Api; @@ -19,4 +21,10 @@ public interface IServerService /// Installation to check /// true if at least one server is using this installation. false otherwise public bool IsInstallationInUse(Installation installation); + + public async Task GetServerByIpAddress(string ipAddress) + { + var results = await GetServersAsync(); + return results.Count == 0 ? null : results.Find(x => x.ServerIp == ipAddress); + } } \ No newline at end of file diff --git a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs index af71c43..f4e0b5c 100644 --- a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs +++ b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs @@ -48,11 +48,20 @@ public bool? TTSEnabled get => _TTSEnabled; set => this.RaiseAndSetIfChanged(ref _TTSEnabled, value); } + + private bool? _allowCodeScan = true; + + public bool? AllowCodeScan + { + get => _allowCodeScan; + set => this.RaiseAndSetIfChanged(ref _allowCodeScan, value); + } private readonly IPreferencesService _preferencesService; private readonly IInstallationService _installationService; private readonly IEnvironmentService _environmentService; private readonly ITTSService _ttsService; + public PreferencesPanelViewModel( IPreferencesService preferencesService, @@ -69,6 +78,7 @@ public PreferencesPanelViewModel( _installationPath = preferences.InstallationPath; _autoRemove = preferences.AutoRemove; _TTSEnabled = preferences.TTSEnabled; + _allowCodeScan = preferences.AllowCodeScan; this.WhenAnyValue(p => p.AutoRemove) .Select(_ => Observable.FromAsync(OnAutoRemoveChangedAsync)) .Concat() @@ -78,6 +88,11 @@ public PreferencesPanelViewModel( .Select(_ => Observable.FromAsync(OnTTSChangedAsync)) .Concat() .Subscribe(); + + this.WhenAnyValue(p => p.AllowCodeScan) + .Select(_ => Observable.FromAsync(OnAllowCodeScanChangedAsync)) + .Concat() + .Subscribe(); } public async Task OnAutoRemoveChangedAsync() @@ -160,6 +175,26 @@ await MessageBoxBuilder.CreateMessageBox(MessageBoxButtons.Ok, "Error moving ins await MessageBoxBuilder.CreateMessageBox(MessageBoxButtons.Ok, "Invalid installation path", invalidReason).ShowAsync(); } } + + public async Task OnAllowCodeScanChangedAsync() + { + if (AllowCodeScan == false) + { + IMsBox msgBox = MessageBoxBuilder.CreateMessageBox( + MessageBoxButtons.YesNo, + "Warning", + "For security reasons, we recommend you never disable the codescan feature unless you're trying to play on older servers that are no longer supported.\n Are you sure you want to proceed?" + ); + + string response = await msgBox.ShowAsync(); + if (response.Equals(MessageBoxResults.No)) + { + AllowCodeScan = true; // Revert the change + } + } + + _preferencesService.GetPreferences().AllowCodeScan = AllowCodeScan; + } public override void Refresh() { diff --git a/UnitystationLauncher/Views/PreferencesPanelView.xaml b/UnitystationLauncher/Views/PreferencesPanelView.xaml index 26b557e..be9fbf0 100644 --- a/UnitystationLauncher/Views/PreferencesPanelView.xaml +++ b/UnitystationLauncher/Views/PreferencesPanelView.xaml @@ -69,6 +69,11 @@ Enable the Text-To-Speech System + + + Enable Code Scan Feature + + From cad94904bcee097b73a0d190efc3dbc96d018d0b Mon Sep 17 00:00:00 2001 From: MaxIsJoe <34368774+MaxIsJoe@users.noreply.github.com> Date: Sat, 5 Jul 2025 21:16:53 +0300 Subject: [PATCH 2/3] rename to _enableCodeScan --- .../Models/ConfigFile/Preferences.cs | 8 ++++---- .../Services/InstallationService.cs | 4 ++-- .../ViewModels/PreferencesPanelViewModel.cs | 18 +++++++++--------- .../Views/PreferencesPanelView.xaml | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/UnitystationLauncher/Models/ConfigFile/Preferences.cs b/UnitystationLauncher/Models/ConfigFile/Preferences.cs index 1377a62..5b0fc33 100644 --- a/UnitystationLauncher/Models/ConfigFile/Preferences.cs +++ b/UnitystationLauncher/Models/ConfigFile/Preferences.cs @@ -8,7 +8,7 @@ public class Preferences : ReactiveObject private int _ignoreVersionUpdate; private string _installationPath = string.Empty; private bool? _TTSEnabled = null; - private bool? _allowCodeScan = true; + private bool? _enableCodeScan = true; public bool AutoRemove { @@ -34,9 +34,9 @@ public bool? TTSEnabled set => this.RaiseAndSetIfChanged(ref _TTSEnabled, value); } - public bool? AllowCodeScan + public bool? EnableCodeScan { - get => _allowCodeScan; - set => this.RaiseAndSetIfChanged(ref _allowCodeScan, value); + get => _enableCodeScan; + set => this.RaiseAndSetIfChanged(ref _enableCodeScan, value); } } diff --git a/UnitystationLauncher/Services/InstallationService.cs b/UnitystationLauncher/Services/InstallationService.cs index 81d5f57..13cbe41 100644 --- a/UnitystationLauncher/Services/InstallationService.cs +++ b/UnitystationLauncher/Services/InstallationService.cs @@ -95,7 +95,7 @@ public List GetInstallations() return (null!, failureReason); } - if (_preferencesService.GetPreferences().AllowCodeScan is true) + if (_preferencesService.GetPreferences().EnableCodeScan is true) { bool result = await _codeScanConfigService.ValidGoodFilesVersionAsync(server.GoodFileVersion); @@ -491,7 +491,7 @@ private async Task StartDownloadAsync(Download download) // ExtractAndScan() must be run in a separate thread, but we want this one to wait for that one to finish // Without this download progress will not work properly - if (_preferencesService.GetPreferences().AllowCodeScan is false) + if (_preferencesService.GetPreferences().EnableCodeScan is false) { await Task.Run(() => Extract(download, progressStream)); } diff --git a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs index f4e0b5c..227c113 100644 --- a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs +++ b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs @@ -49,12 +49,12 @@ public bool? TTSEnabled set => this.RaiseAndSetIfChanged(ref _TTSEnabled, value); } - private bool? _allowCodeScan = true; + private bool? _enableCodeScan = true; - public bool? AllowCodeScan + public bool? EnableCodeScan { - get => _allowCodeScan; - set => this.RaiseAndSetIfChanged(ref _allowCodeScan, value); + get => _enableCodeScan; + set => this.RaiseAndSetIfChanged(ref _enableCodeScan, value); } private readonly IPreferencesService _preferencesService; @@ -78,7 +78,7 @@ public PreferencesPanelViewModel( _installationPath = preferences.InstallationPath; _autoRemove = preferences.AutoRemove; _TTSEnabled = preferences.TTSEnabled; - _allowCodeScan = preferences.AllowCodeScan; + _enableCodeScan = preferences.EnableCodeScan; this.WhenAnyValue(p => p.AutoRemove) .Select(_ => Observable.FromAsync(OnAutoRemoveChangedAsync)) .Concat() @@ -89,7 +89,7 @@ public PreferencesPanelViewModel( .Concat() .Subscribe(); - this.WhenAnyValue(p => p.AllowCodeScan) + this.WhenAnyValue(p => p.EnableCodeScan) .Select(_ => Observable.FromAsync(OnAllowCodeScanChangedAsync)) .Concat() .Subscribe(); @@ -178,7 +178,7 @@ await MessageBoxBuilder.CreateMessageBox(MessageBoxButtons.Ok, "Error moving ins public async Task OnAllowCodeScanChangedAsync() { - if (AllowCodeScan == false) + if (EnableCodeScan == false) { IMsBox msgBox = MessageBoxBuilder.CreateMessageBox( MessageBoxButtons.YesNo, @@ -189,11 +189,11 @@ public async Task OnAllowCodeScanChangedAsync() string response = await msgBox.ShowAsync(); if (response.Equals(MessageBoxResults.No)) { - AllowCodeScan = true; // Revert the change + EnableCodeScan = true; // Revert the change } } - _preferencesService.GetPreferences().AllowCodeScan = AllowCodeScan; + _preferencesService.GetPreferences().EnableCodeScan = EnableCodeScan; } public override void Refresh() diff --git a/UnitystationLauncher/Views/PreferencesPanelView.xaml b/UnitystationLauncher/Views/PreferencesPanelView.xaml index be9fbf0..0bcae26 100644 --- a/UnitystationLauncher/Views/PreferencesPanelView.xaml +++ b/UnitystationLauncher/Views/PreferencesPanelView.xaml @@ -70,7 +70,7 @@ - + Enable Code Scan Feature From e83e6217f1dd61a298db79974ec856d681e0a4bb Mon Sep 17 00:00:00 2001 From: MaxIsJoe <34368774+MaxIsJoe@users.noreply.github.com> Date: Mon, 7 Jul 2025 00:26:11 +0300 Subject: [PATCH 3/3] Update PreferencesPanelViewModel.cs --- UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs index 227c113..9c95e07 100644 --- a/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs +++ b/UnitystationLauncher/ViewModels/PreferencesPanelViewModel.cs @@ -183,7 +183,7 @@ public async Task OnAllowCodeScanChangedAsync() IMsBox msgBox = MessageBoxBuilder.CreateMessageBox( MessageBoxButtons.YesNo, "Warning", - "For security reasons, we recommend you never disable the codescan feature unless you're trying to play on older servers that are no longer supported.\n Are you sure you want to proceed?" + "For security reasons, we recommend you never disable the codescan feature unless you understand what you are doing and you trust the server you are trying to play on.\n Are you sure you want to proceed?" ); string response = await msgBox.ShowAsync();