Fix and improve valid install path checks

+ Fail if child of game folder
+ Fail if child of Program Files
+ Add test for null path
* Fix success if path null
* Check if install path exists before updating download path
This commit is contained in:
Unnoen 2021-05-20 19:54:57 +10:00
parent 367ee1a3aa
commit 9d890f2ff0
No known key found for this signature in database
GPG Key ID: 8F8E42252BA20553
3 changed files with 29 additions and 11 deletions

View File

@ -1,4 +1,4 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@ -22,6 +22,7 @@ using File = Alphaleonis.Win32.Filesystem.File;
using Path = Alphaleonis.Win32.Filesystem.Path; using Path = Alphaleonis.Win32.Filesystem.Path;
using SectionData = Wabbajack.Common.SectionData; using SectionData = Wabbajack.Common.SectionData;
using System.Collections.Generic; using System.Collections.Generic;
using Wabbajack.Common.IO;
using Wabbajack.Lib.ModListRegistry; using Wabbajack.Lib.ModListRegistry;
using Wabbajack.VirtualFileSystem; using Wabbajack.VirtualFileSystem;
@ -503,14 +504,24 @@ namespace Wabbajack.Lib
await OutputFolder.Combine(directive.To).WriteAllTextAsync(data); await OutputFolder.Combine(directive.To).WriteAllTextAsync(data);
} }
public static IErrorResponse CheckValidInstallPath(AbsolutePath path, AbsolutePath? downloadFolder) public static IErrorResponse CheckValidInstallPath(AbsolutePath path, AbsolutePath? downloadFolder, GameMetaData? game)
{ {
// Check if null path
if (string.IsNullOrEmpty(path.ToString())) return ErrorResponse.Fail("Please select an install directory.");
// Check if child of game folder
if (game?.TryGetGameLocation() != null && path.IsChildOf(game.TryGetGameLocation())) return ErrorResponse.Fail("Cannot install to game directory.");
// Check if child of Program Files
if (path.IsChildOf(new AbsolutePath(KnownFolders.ProgramFiles.Path))) return ErrorResponse.Fail("Cannot install to Program Files directory.");
// If the folder doesn't exist, it's empty so we don't need to check further
if (!path.Exists) return ErrorResponse.Success; if (!path.Exists) return ErrorResponse.Success;
// Check folder does not have a Wabbajack ModList // Check folder does not have a Wabbajack ModList
if (path.EnumerateFiles(false).Where(file => file.Exists).Any(file => file.Extension == Consts.ModListExtension)) if (path.EnumerateFiles(false).Where(file => file.Exists).Any(file => file.Extension == Consts.ModListExtension))
{ {
return ErrorResponse.Fail($"Cannot install into a folder with a Wabbajack ModList inside of it"); return ErrorResponse.Fail($"Cannot install into a folder with a Wabbajack ModList inside of it.");
} }
// Check if folder is empty // Check if folder is empty

View File

@ -13,14 +13,14 @@ namespace Wabbajack.Test
public async Task CheckValidInstallPath_Empty() public async Task CheckValidInstallPath_Empty()
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
public async Task CheckValidInstallPath_DoesNotExist() public async Task CheckValidInstallPath_DoesNotExist()
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir.Combine("Subfolder"), downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir.Combine("Subfolder"), null, null).Succeeded);
} }
[Fact] [Fact]
@ -29,7 +29,7 @@ namespace Wabbajack.Test
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
await using var mo2 = await tempDir.Dir.Combine("ModOrganizer.exe").Create(); await using var mo2 = await tempDir.Dir.Combine("ModOrganizer.exe").Create();
await using var molist = await tempDir.Dir.Combine(((RelativePath)"modlist")).WithExtension(Consts.ModListExtension).Create(); await using var molist = await tempDir.Dir.Combine(((RelativePath)"modlist")).WithExtension(Consts.ModListExtension).Create();
Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -37,7 +37,7 @@ namespace Wabbajack.Test
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
await using var tmp = await tempDir.Dir.Combine(Consts.ModOrganizer2Exe).Create(); await using var tmp = await tempDir.Dir.Combine(Consts.ModOrganizer2Exe).Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -47,7 +47,7 @@ namespace Wabbajack.Test
await tempDir.Dir.DeleteDirectory(); await tempDir.Dir.DeleteDirectory();
tempDir.Dir.CreateDirectory(); tempDir.Dir.CreateDirectory();
await using var tmp = await tempDir.Dir.Combine($"someFile.txt").Create(); await using var tmp = await tempDir.Dir.Combine($"someFile.txt").Create();
Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -57,7 +57,14 @@ namespace Wabbajack.Test
var downloadsFolder = tempDir.Dir.Combine("downloads"); var downloadsFolder = tempDir.Dir.Combine("downloads");
downloadsFolder.CreateDirectory(); downloadsFolder.CreateDirectory();
await using var tmp = await tempDir.Dir.Combine($"downloads/someFile.txt").Create(); await using var tmp = await tempDir.Dir.Combine($"downloads/someFile.txt").Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: downloadsFolder).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadsFolder, null).Succeeded);
}
[Fact]
public async Task CheckValidInstallPath_NullPath()
{
var tempDir = new AbsolutePath("", true);
Assert.True(MO2Installer.CheckValidInstallPath(tempDir, null, null).Succeeded == false);
} }
#endregion #endregion
} }

View File

@ -63,7 +63,7 @@ namespace Wabbajack
this.WhenAny(x => x.DownloadLocation.TargetPath), this.WhenAny(x => x.DownloadLocation.TargetPath),
resultSelector: (target, download) => (target, download)) resultSelector: (target, download) => (target, download))
.ObserveOn(RxApp.TaskpoolScheduler) .ObserveOn(RxApp.TaskpoolScheduler)
.Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download)) .Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download, Parent.ModList.SourceModList.GameType.MetaData()))
.ObserveOnGuiThread(); .ObserveOnGuiThread();
_CanInstall = Observable.CombineLatest( _CanInstall = Observable.CombineLatest(
@ -83,7 +83,7 @@ namespace Wabbajack
{ {
if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath) if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath)
{ {
DownloadLocation.TargetPath = installPath.Combine("downloads"); if (installPath.Exists) DownloadLocation.TargetPath = installPath.Combine("downloads");
} }
}) })
.DisposeWith(CompositeDisposable); .DisposeWith(CompositeDisposable);