diff --git a/src/NzbDrone.Core/Organizer/FileNameValidation.cs b/src/NzbDrone.Core/Organizer/FileNameValidation.cs index 5366f709f..3bc15e94f 100644 --- a/src/NzbDrone.Core/Organizer/FileNameValidation.cs +++ b/src/NzbDrone.Core/Organizer/FileNameValidation.cs @@ -1,6 +1,10 @@ -using System.Text.RegularExpressions; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; using FluentValidation; using FluentValidation.Validators; +using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Organizer { @@ -15,36 +19,48 @@ namespace NzbDrone.Core.Organizer public static IRuleBuilderOptions ValidEpisodeFormat(this IRuleBuilder ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new IllegalCharactersValidator()); + return ruleBuilder.SetValidator(new ValidStandardEpisodeFormatValidator()); } public static IRuleBuilderOptions ValidDailyEpisodeFormat(this IRuleBuilder ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new IllegalCharactersValidator()); + return ruleBuilder.SetValidator(new ValidDailyEpisodeFormatValidator()); } public static IRuleBuilderOptions ValidAnimeEpisodeFormat(this IRuleBuilder ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new IllegalCharactersValidator()); + return ruleBuilder.SetValidator(new ValidAnimeEpisodeFormatValidator()); } public static IRuleBuilderOptions ValidSeriesFolderFormat(this IRuleBuilder ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new IllegalCharactersValidator()); + return ruleBuilder.SetValidator(new RegularExpressionValidator(FileNameBuilder.SeriesTitleRegex)).WithMessage("Must contain series title"); } public static IRuleBuilderOptions ValidSeasonFolderFormat(this IRuleBuilder ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new IllegalCharactersValidator()); + return ruleBuilder.SetValidator(new RegularExpressionValidator(SeasonFolderRegex)).WithMessage("Must contain season number"); } public static IRuleBuilderOptions ValidSpecialsFolderFormat(this IRuleBuilder ruleBuilder) { - return ruleBuilder.SetValidator(new NotEmptyValidator(null)); + ruleBuilder.SetValidator(new NotEmptyValidator(null)); + + return ruleBuilder.SetValidator(new IllegalCharactersValidator()); } } @@ -115,4 +131,42 @@ namespace NzbDrone.Core.Organizer return true; } } + + public class IllegalCharactersValidator : PropertyValidator + { + private readonly char[] _invalidPathChars = Path.GetInvalidPathChars(); + + public IllegalCharactersValidator() + : base("Contains illegal characters: {InvalidCharacters}") + { + + } + + protected override bool IsValid(PropertyValidatorContext context) + { + var value = context.PropertyValue as string; + var invalidCharacters = new List(); + + if (value.IsNullOrWhiteSpace()) + { + return true; + } + + foreach (var i in _invalidPathChars) + { + if (value.IndexOf(i) >= 0) + { + invalidCharacters.Add(i); + } + } + + if (invalidCharacters.Any()) + { + context.MessageFormatter.AppendArgument("InvalidCharacters", string.Join("", invalidCharacters)); + return false; + } + + return true; + } + } }