diff --git a/src/NzbDrone.Common.Test/EnsureTest/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/EnsureTest/PathExtensionFixture.cs index 53c1b42f4..42a65f9b1 100644 --- a/src/NzbDrone.Common.Test/EnsureTest/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/EnsureTest/PathExtensionFixture.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using NzbDrone.Common.Disk; using NzbDrone.Common.EnsureThat; using NzbDrone.Test.Common; @@ -12,14 +13,14 @@ namespace NzbDrone.Common.Test.EnsureTest public void EnsureWindowsPath(string path) { WindowsOnly(); - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); } [TestCase(@"/var/user/file with, comma.mkv")] public void EnsureLinuxPath(string path) { PosixOnly(); - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); } } } diff --git a/src/NzbDrone.Common.Test/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/PathExtensionFixture.cs index a01c6dc1a..a33a53c01 100644 --- a/src/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -35,6 +35,7 @@ namespace NzbDrone.Common.Test [TestCase(@"\\Testserver\Test\file.ext", @"\\Testserver\Test\file.ext")] [TestCase(@"\\Testserver\Test\file.ext\\", @"\\Testserver\Test\file.ext")] [TestCase(@"\\Testserver\Test\file.ext \\", @"\\Testserver\Test\file.ext")] + [TestCase(@"//CAPITAL//lower// ", @"\\CAPITAL\lower")] public void Clean_Path_Windows(string dirty, string clean) { WindowsOnly(); diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index 29de0c1a6..5e9228236 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -65,7 +65,7 @@ namespace NzbDrone.Common.Disk private void CheckFolderExists(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); if (!FolderExists(path)) { @@ -75,7 +75,7 @@ namespace NzbDrone.Common.Disk private void CheckFileExists(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); if (!FileExists(path)) { @@ -93,19 +93,19 @@ namespace NzbDrone.Common.Disk public bool FolderExists(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return Directory.Exists(path); } public bool FileExists(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return FileExists(path, PathStringComparison); } public bool FileExists(string path, StringComparison stringComparison) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); switch (stringComparison) { @@ -125,7 +125,7 @@ namespace NzbDrone.Common.Disk public bool FolderWritable(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); try { @@ -144,35 +144,35 @@ namespace NzbDrone.Common.Disk public bool FolderEmpty(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return Directory.EnumerateFileSystemEntries(path).Empty(); } public string[] GetDirectories(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return Directory.GetDirectories(path); } public string[] GetFiles(string path, SearchOption searchOption) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return Directory.GetFiles(path, "*.*", searchOption); } public long GetFolderSize(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length); } public long GetFileSize(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); if (!FileExists(path)) { @@ -185,13 +185,13 @@ namespace NzbDrone.Common.Disk public void CreateFolder(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); Directory.CreateDirectory(path); } public void DeleteFile(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); Logger.Trace("Deleting file: {0}", path); RemoveReadOnly(path); @@ -201,8 +201,8 @@ namespace NzbDrone.Common.Disk public void CloneFile(string source, string destination, bool overwrite = false) { - Ensure.That(source, () => source).IsValidPath(); - Ensure.That(destination, () => destination).IsValidPath(); + Ensure.That(source, () => source).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(destination, () => destination).IsValidPath(PathValidationType.CurrentOs); if (source.PathEquals(destination)) { @@ -219,8 +219,8 @@ namespace NzbDrone.Common.Disk public void CopyFile(string source, string destination, bool overwrite = false) { - Ensure.That(source, () => source).IsValidPath(); - Ensure.That(destination, () => destination).IsValidPath(); + Ensure.That(source, () => source).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(destination, () => destination).IsValidPath(PathValidationType.CurrentOs); if (source.PathEquals(destination)) { @@ -237,8 +237,8 @@ namespace NzbDrone.Common.Disk public void MoveFile(string source, string destination, bool overwrite = false) { - Ensure.That(source, () => source).IsValidPath(); - Ensure.That(destination, () => destination).IsValidPath(); + Ensure.That(source, () => source).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(destination, () => destination).IsValidPath(PathValidationType.CurrentOs); if (source.PathEquals(destination)) { @@ -256,8 +256,8 @@ namespace NzbDrone.Common.Disk public void MoveFolder(string source, string destination, bool overwrite = false) { - Ensure.That(source, () => source).IsValidPath(); - Ensure.That(destination, () => destination).IsValidPath(); + Ensure.That(source, () => source).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(destination, () => destination).IsValidPath(PathValidationType.CurrentOs); Directory.Move(source, destination); } @@ -281,7 +281,7 @@ namespace NzbDrone.Common.Disk public void DeleteFolder(string path, bool recursive) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var files = Directory.GetFiles(path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); Array.ForEach(files, RemoveReadOnly); @@ -291,14 +291,14 @@ namespace NzbDrone.Common.Disk public string ReadAllText(string filePath) { - Ensure.That(filePath, () => filePath).IsValidPath(); + Ensure.That(filePath, () => filePath).IsValidPath(PathValidationType.CurrentOs); return File.ReadAllText(filePath); } public void WriteAllText(string filename, string contents) { - Ensure.That(filename, () => filename).IsValidPath(); + Ensure.That(filename, () => filename).IsValidPath(PathValidationType.CurrentOs); RemoveReadOnly(filename); // File.WriteAllText is broken on net core when writing to some CIFS mounts @@ -314,7 +314,7 @@ namespace NzbDrone.Common.Disk public void FolderSetLastWriteTime(string path, DateTime dateTime) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); if (dateTime.Before(DateTimeExtensions.Epoch)) { @@ -326,7 +326,7 @@ namespace NzbDrone.Common.Disk public void FileSetLastWriteTime(string path, DateTime dateTime) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); if (dateTime.Before(DateTimeExtensions.Epoch)) { @@ -353,14 +353,14 @@ namespace NzbDrone.Common.Disk public virtual string GetPathRoot(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return Path.GetPathRoot(path); } public string GetParentFolder(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var parent = Directory.GetParent(path.TrimEnd(Path.DirectorySeparatorChar)); @@ -407,7 +407,7 @@ namespace NzbDrone.Common.Disk public void EmptyFolder(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); foreach (var file in GetFiles(path, SearchOption.TopDirectoryOnly)) { @@ -496,7 +496,7 @@ namespace NzbDrone.Common.Disk public List GetDirectoryInfos(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var di = new DirectoryInfo(path); @@ -505,14 +505,14 @@ namespace NzbDrone.Common.Disk public FileInfo GetFileInfo(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); return new FileInfo(path); } public List GetFileInfos(string path, SearchOption searchOption = SearchOption.TopDirectoryOnly) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var di = new DirectoryInfo(path); diff --git a/src/NzbDrone.Common/Disk/DiskTransferService.cs b/src/NzbDrone.Common/Disk/DiskTransferService.cs index 44d28a9df..83d815348 100644 --- a/src/NzbDrone.Common/Disk/DiskTransferService.cs +++ b/src/NzbDrone.Common/Disk/DiskTransferService.cs @@ -43,8 +43,8 @@ namespace NzbDrone.Common.Disk public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode) { - Ensure.That(sourcePath, () => sourcePath).IsValidPath(); - Ensure.That(targetPath, () => targetPath).IsValidPath(); + Ensure.That(sourcePath, () => sourcePath).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(targetPath, () => targetPath).IsValidPath(PathValidationType.CurrentOs); sourcePath = ResolveRealParentPath(sourcePath); targetPath = ResolveRealParentPath(targetPath); @@ -140,8 +140,8 @@ namespace NzbDrone.Common.Disk { var filesCopied = 0; - Ensure.That(sourcePath, () => sourcePath).IsValidPath(); - Ensure.That(targetPath, () => targetPath).IsValidPath(); + Ensure.That(sourcePath, () => sourcePath).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(targetPath, () => targetPath).IsValidPath(PathValidationType.CurrentOs); sourcePath = ResolveRealParentPath(sourcePath); targetPath = ResolveRealParentPath(targetPath); @@ -255,8 +255,8 @@ namespace NzbDrone.Common.Disk public TransferMode TransferFile(string sourcePath, string targetPath, TransferMode mode, bool overwrite = false) { - Ensure.That(sourcePath, () => sourcePath).IsValidPath(); - Ensure.That(targetPath, () => targetPath).IsValidPath(); + Ensure.That(sourcePath, () => sourcePath).IsValidPath(PathValidationType.CurrentOs); + Ensure.That(targetPath, () => targetPath).IsValidPath(PathValidationType.CurrentOs); sourcePath = ResolveRealParentPath(sourcePath); targetPath = ResolveRealParentPath(targetPath); diff --git a/src/NzbDrone.Common/Disk/FileSystemLookupService.cs b/src/NzbDrone.Common/Disk/FileSystemLookupService.cs index 63529697e..8b9d1bae0 100644 --- a/src/NzbDrone.Common/Disk/FileSystemLookupService.cs +++ b/src/NzbDrone.Common/Disk/FileSystemLookupService.cs @@ -71,7 +71,7 @@ namespace NzbDrone.Common.Disk if ( allowFoldersWithoutTrailingSlashes && - query.IsPathValid() && + query.IsPathValid(PathValidationType.CurrentOs) && _diskProvider.FolderExists(query)) { return GetResult(query, includeFiles); diff --git a/src/NzbDrone.Common/Disk/OsPath.cs b/src/NzbDrone.Common/Disk/OsPath.cs index c4327ddeb..84942a186 100644 --- a/src/NzbDrone.Common/Disk/OsPath.cs +++ b/src/NzbDrone.Common/Disk/OsPath.cs @@ -162,7 +162,7 @@ namespace NzbDrone.Common.Disk } } - public bool IsValid => _path.IsPathValid(); + public bool IsValid => _path.IsPathValid(PathValidationType.CurrentOs); private int GetFileNameIndex() { diff --git a/src/NzbDrone.Common/Disk/PathValidationType.cs b/src/NzbDrone.Common/Disk/PathValidationType.cs new file mode 100644 index 000000000..395e3f0d8 --- /dev/null +++ b/src/NzbDrone.Common/Disk/PathValidationType.cs @@ -0,0 +1,8 @@ +namespace NzbDrone.Common.Disk +{ + public enum PathValidationType + { + CurrentOs, + AnyOs + } +} diff --git a/src/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs b/src/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs index 1c10c9f28..ba02ee7f6 100644 --- a/src/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs +++ b/src/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Text.RegularExpressions; +using NzbDrone.Common.Disk; using NzbDrone.Common.EnsureThat.Resources; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; @@ -111,14 +112,14 @@ namespace NzbDrone.Common.EnsureThat } [DebuggerStepThrough] - public static Param IsValidPath(this Param param) + public static Param IsValidPath(this Param param, PathValidationType validationType) { if (string.IsNullOrWhiteSpace(param.Value)) { throw ExceptionFactory.CreateForParamValidation(param.Name, ExceptionMessages.EnsureExtensions_IsNotNullOrWhiteSpace); } - if (param.Value.IsPathValid()) + if (param.Value.IsPathValid(validationType)) { return param; } diff --git a/src/NzbDrone.Common/Extensions/PathExtensions.cs b/src/NzbDrone.Common/Extensions/PathExtensions.cs index cf82e601c..f2d82f10e 100644 --- a/src/NzbDrone.Common/Extensions/PathExtensions.cs +++ b/src/NzbDrone.Common/Extensions/PathExtensions.cs @@ -29,12 +29,12 @@ namespace NzbDrone.Common.Extensions public static string CleanFilePath(this string path) { Ensure.That(path, () => path).IsNotNullOrWhiteSpace(); - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.AnyOs); var info = new FileInfo(path.Trim()); // UNC - if (OsInfo.IsWindows && info.FullName.StartsWith(@"\\")) + if (!info.FullName.Contains('/') && info.FullName.StartsWith(@"\\")) { return info.FullName.TrimEnd('/', '\\', ' '); } @@ -136,24 +136,24 @@ namespace NzbDrone.Common.Extensions private static readonly Regex WindowsPathWithDriveRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled); - public static bool IsPathValid(this string path) + public static bool IsPathValid(this string path, PathValidationType validationType) { if (path.ContainsInvalidPathChars() || string.IsNullOrWhiteSpace(path)) { return false; } - if (OsInfo.IsNotWindows) + if (validationType == PathValidationType.AnyOs) { - return path.StartsWith(Path.DirectorySeparatorChar.ToString()); + return IsPathValidForWindows(path) || IsPathValidForNonWindows(path); } - if (path.StartsWith("\\") || WindowsPathWithDriveRegex.IsMatch(path)) + if (OsInfo.IsNotWindows) { - return true; + return IsPathValidForNonWindows(path); } - return false; + return IsPathValidForWindows(path); } public static bool ContainsInvalidPathChars(this string text) @@ -337,5 +337,15 @@ namespace NzbDrone.Common.Extensions { return Path.Combine(appFolderInfo.StartUpFolder, NLOG_CONFIG_FILE); } + + private static bool IsPathValidForWindows(string path) + { + return path.StartsWith("\\") || WindowsPathWithDriveRegex.IsMatch(path); + } + + private static bool IsPathValidForNonWindows(string path) + { + return path.StartsWith("/"); + } } } diff --git a/src/NzbDrone.Common/PathEqualityComparer.cs b/src/NzbDrone.Common/PathEqualityComparer.cs index d443a3bf0..958b700db 100644 --- a/src/NzbDrone.Common/PathEqualityComparer.cs +++ b/src/NzbDrone.Common/PathEqualityComparer.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; diff --git a/src/NzbDrone.Core/Validation/FolderValidator.cs b/src/NzbDrone.Core/Validation/FolderValidator.cs index 6f88c9009..405fe14bd 100644 --- a/src/NzbDrone.Core/Validation/FolderValidator.cs +++ b/src/NzbDrone.Core/Validation/FolderValidator.cs @@ -1,4 +1,5 @@ -using FluentValidation.Validators; +using FluentValidation.Validators; +using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Validation @@ -14,7 +15,7 @@ namespace NzbDrone.Core.Validation return false; } - return context.PropertyValue.ToString().IsPathValid(); + return context.PropertyValue.ToString().IsPathValid(PathValidationType.CurrentOs); } } } diff --git a/src/NzbDrone.Core/Validation/Paths/PathValidator.cs b/src/NzbDrone.Core/Validation/Paths/PathValidator.cs index fe0b496ed..831d0e2a7 100644 --- a/src/NzbDrone.Core/Validation/Paths/PathValidator.cs +++ b/src/NzbDrone.Core/Validation/Paths/PathValidator.cs @@ -1,5 +1,6 @@ -using FluentValidation; +using FluentValidation; using FluentValidation.Validators; +using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Validation.Paths @@ -23,7 +24,7 @@ namespace NzbDrone.Core.Validation.Paths return false; } - return context.PropertyValue.ToString().IsPathValid(); + return context.PropertyValue.ToString().IsPathValid(PathValidationType.CurrentOs); } } } diff --git a/src/NzbDrone.Mono/Disk/DiskProvider.cs b/src/NzbDrone.Mono/Disk/DiskProvider.cs index e8d25b3e8..720bf211c 100644 --- a/src/NzbDrone.Mono/Disk/DiskProvider.cs +++ b/src/NzbDrone.Mono/Disk/DiskProvider.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Mono.Disk public override long? GetAvailableSpace(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var mount = GetMount(path); @@ -217,7 +217,7 @@ namespace NzbDrone.Mono.Disk public override long? GetTotalSize(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var mount = GetMount(path); diff --git a/src/NzbDrone.Windows/Disk/DiskProvider.cs b/src/NzbDrone.Windows/Disk/DiskProvider.cs index 3200e669b..f65dae3d0 100644 --- a/src/NzbDrone.Windows/Disk/DiskProvider.cs +++ b/src/NzbDrone.Windows/Disk/DiskProvider.cs @@ -35,7 +35,7 @@ namespace NzbDrone.Windows.Disk public override string GetPathRoot(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var reparsePoint = GetReparsePoint(path); @@ -44,7 +44,7 @@ namespace NzbDrone.Windows.Disk public override long? GetAvailableSpace(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var root = GetPathRoot(path); @@ -58,7 +58,7 @@ namespace NzbDrone.Windows.Disk public override void InheritFolderPermissions(string filename) { - Ensure.That(filename, () => filename).IsValidPath(); + Ensure.That(filename, () => filename).IsValidPath(PathValidationType.CurrentOs); var fileInfo = new FileInfo(filename); var fs = fileInfo.GetAccessControl(AccessControlSections.Access); @@ -121,7 +121,7 @@ namespace NzbDrone.Windows.Disk public override long? GetTotalSize(string path) { - Ensure.That(path, () => path).IsValidPath(); + Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs); var root = GetPathRoot(path); @@ -135,7 +135,7 @@ namespace NzbDrone.Windows.Disk private static long DriveFreeSpaceEx(string folderName) { - Ensure.That(folderName, () => folderName).IsValidPath(); + Ensure.That(folderName, () => folderName).IsValidPath(PathValidationType.CurrentOs); if (!folderName.EndsWith("\\")) { @@ -156,7 +156,7 @@ namespace NzbDrone.Windows.Disk private static long DriveTotalSizeEx(string folderName) { - Ensure.That(folderName, () => folderName).IsValidPath(); + Ensure.That(folderName, () => folderName).IsValidPath(PathValidationType.CurrentOs); if (!folderName.EndsWith("\\")) {