diff --git a/src/NzbDrone.Common.Test/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/PathExtensionFixture.cs index 00012a135..323f14dd4 100644 --- a/src/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -3,6 +3,7 @@ using System.IO; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; using NzbDrone.Test.Common; @@ -335,5 +336,30 @@ namespace NzbDrone.Common.Test result[2].Should().Be(@"TV"); result[3].Should().Be(@"Series Title"); } + + [TestCase(@"C:\Test\")] + [TestCase(@"C:\Test")] + [TestCase(@"C:\Test\TV\")] + [TestCase(@"C:\Test\TV")] + public void IsPathValid_should_be_true(string path) + { + path.AsOsAgnostic().IsPathValid(PathValidationType.CurrentOs).Should().BeTrue(); + } + + [TestCase(@"C:\Test \")] + [TestCase(@"C:\Test ")] + [TestCase(@"C:\ Test\")] + [TestCase(@"C:\ Test")] + [TestCase(@"C:\Test \TV")] + [TestCase(@"C:\ Test\TV")] + [TestCase(@"C:\Test \TV\")] + [TestCase(@"C:\ Test\TV\")] + [TestCase(@" C:\Test\TV\")] + [TestCase(@" C:\Test\TV")] + + public void IsPathValid_should_be_false(string path) + { + path.AsOsAgnostic().IsPathValid(PathValidationType.CurrentOs).Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Common/Extensions/PathExtensions.cs b/src/NzbDrone.Common/Extensions/PathExtensions.cs index 280083e4c..a61830931 100644 --- a/src/NzbDrone.Common/Extensions/PathExtensions.cs +++ b/src/NzbDrone.Common/Extensions/PathExtensions.cs @@ -154,6 +154,23 @@ namespace NzbDrone.Common.Extensions return false; } + if (path.Trim() != path) + { + return false; + } + + var directoryInfo = new DirectoryInfo(path); + + while (directoryInfo != null) + { + if (directoryInfo.Name.Trim() != directoryInfo.Name) + { + return false; + } + + directoryInfo = directoryInfo.Parent; + } + if (validationType == PathValidationType.AnyOs) { return IsPathValidForWindows(path) || IsPathValidForNonWindows(path); @@ -291,6 +308,11 @@ namespace NzbDrone.Common.Extensions return processName; } + public static string CleanPath(this string path) + { + return Path.Join(path.Split(Path.DirectorySeparatorChar).Select(s => s.Trim()).ToArray()); + } + public static string GetAppDataPath(this IAppFolderInfo appFolderInfo) { return appFolderInfo.AppDataFolder; diff --git a/src/Sonarr.Api.V3/Series/SeriesController.cs b/src/Sonarr.Api.V3/Series/SeriesController.cs index 14ee8f465..e1d50ec0f 100644 --- a/src/Sonarr.Api.V3/Series/SeriesController.cs +++ b/src/Sonarr.Api.V3/Series/SeriesController.cs @@ -92,8 +92,6 @@ namespace Sonarr.Api.V3.Series .When(s => s.Path.IsNullOrWhiteSpace()); PostValidator.RuleFor(s => s.Title).NotEmpty(); PostValidator.RuleFor(s => s.TvdbId).GreaterThan(0).SetValidator(seriesExistsValidator); - - PutValidator.RuleFor(s => s.Path).IsValidPath(); } [HttpGet]