Validate Special Folder Format doesn't match excluded folder

Closes #8339
This commit is contained in:
Mark McDowall 2026-01-12 20:04:01 -08:00
parent 7eabd1bb7a
commit 43d5abc1fe
No known key found for this signature in database
2 changed files with 53 additions and 1 deletions

View file

@ -245,6 +245,28 @@ public List<string> FilterPaths(string basePath, IEnumerable<string> paths, bool
return filteredPaths;
}
public static List<string> FilteredSubFolderMatches(string subfolder)
{
var matches = new List<string>();
foreach (var match in ExcludedSubFoldersRegex.Matches(subfolder))
{
matches.Add(match.ToString());
}
foreach (var match in ExcludedExtrasSubFolderRegex.Matches(subfolder))
{
matches.Add(match.ToString());
}
foreach (var match in ExcludedExtraFilesRegex.Matches(subfolder))
{
matches.Add(match.ToString());
}
return matches;
}
private void SetPermissions(string path)
{
if (!_configService.SetPermissionsLinux)

View file

@ -5,6 +5,7 @@
using FluentValidation;
using FluentValidation.Validators;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Organizer
{
@ -59,8 +60,9 @@ public static IRuleBuilderOptions<T, string> ValidSeasonFolderFormat<T>(this IRu
public static IRuleBuilderOptions<T, string> ValidSpecialsFolderFormat<T>(this IRuleBuilder<T, string> ruleBuilder)
{
ruleBuilder.SetValidator(new NotEmptyValidator(null));
ruleBuilder.SetValidator(new IllegalCharactersValidator());
return ruleBuilder.SetValidator(new IllegalCharactersValidator());
return ruleBuilder.SetValidator(new FilteredSubfolderValidator());
}
public static IRuleBuilderOptions<T, string> ValidCustomColonReplacement<T>(this IRuleBuilder<T, string> ruleBuilder)
@ -177,4 +179,32 @@ protected override bool IsValid(PropertyValidatorContext context)
return true;
}
}
public class FilteredSubfolderValidator : PropertyValidator
{
private static readonly char[] InvalidPathChars = Path.GetInvalidPathChars();
protected override string GetDefaultMessageTemplate() => "Matches excluded subfolder pattern: {FilteredSubfolders}";
protected override bool IsValid(PropertyValidatorContext context)
{
var value = context.PropertyValue as string;
if (value.IsNullOrWhiteSpace())
{
return true;
}
var subfolder = value + Path.DirectorySeparatorChar;
var matches = DiskScanService.FilteredSubFolderMatches(subfolder);
if (matches.Any())
{
context.MessageFormatter.AppendArgument("FilteredSubfolders", string.Join("", matches.Select(m => m.TrimEnd(Path.DirectorySeparatorChar))));
return false;
}
return true;
}
}
}