diff --git a/anbs_cpdb/anbs_cpdb.csproj b/anbs_cpdb/anbs_cpdb.csproj index 6d19bcc..58ca5bb 100644 --- a/anbs_cpdb/anbs_cpdb.csproj +++ b/anbs_cpdb/anbs_cpdb.csproj @@ -8,7 +8,7 @@ anbs_cp.Database True ANBSoftware.ComponentsPack.Database - 2024.2.6.0 + 2024.3.11.0 Александр Бабаев Набор компонентов ANB Software для работы с БД Библиотека полезных методов языка C# для работы с базами данных @@ -16,10 +16,11 @@ https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack git + Александр Бабаев - + diff --git a/anbs_cpfn/Classes/Sanitizer.cs b/anbs_cpfn/Classes/Sanitizer.cs index e5357ad..3344f61 100644 --- a/anbs_cpfn/Classes/Sanitizer.cs +++ b/anbs_cpfn/Classes/Sanitizer.cs @@ -1,5 +1,4 @@ using anbs_cp.ForNet.Enums; - using Ganss.Xss; namespace anbs_cp.ForNet.Classes; @@ -9,47 +8,53 @@ namespace anbs_cp.ForNet.Classes; /// public static class Sanitizer { + #region Свойства + /// - /// Очистка текста по уровню очистки + /// Все теги запрещены /// - /// Текст - /// Уровень очистка - /// Очищенный текст - public static string SanitizeHtml (string html, ESanitizerLevel level) + public static SanitizerAllowedHtml AllowedNone => GetNone(); + + /// + /// Все теги разрешены + /// + public static SanitizerAllowedHtml AllowedAll => GetAll(); + + /// + /// Оставлены только текстовые теги + /// + public static SanitizerAllowedHtml AllowedTextOnly => GetTextFormatOnly(); + + /// + /// Оставлены только текстовые теги, а также img и a + /// + public static SanitizerAllowedHtml AllowedImageAndLinks => GetImageAndLinks(); + + /// + /// Применяются все теги, кроме iframe + /// + public static SanitizerAllowedHtml AllowedAllExceptIFrame => GetAllExceptIFrame(); + + #endregion + + #region Методы + + /// + /// Очистка html-кода согласно параметрам + /// + /// HTML-код + /// Параметры очистки + /// Очищенный html-кода + private static string SanitizeHtml(string html, SanitizerAllowedHtml allowedHtml) { + // Создаю очиститель HtmlSanitizer sanitizer = new() { + // - сохраняю дочерние удалённых KeepChildNodes = true }; - switch (level) - { - case ESanitizerLevel.NoTags: - PrepareForNone(ref sanitizer); - break; - case ESanitizerLevel.TextFormatOnly: - PrepareForTextFormatOnly(ref sanitizer); - break; - case ESanitizerLevel.ImageAndLinks: - PrepareForImageAndLinks(ref sanitizer); - break; - case ESanitizerLevel.AllExceptIFrame: - PrepareForAllExceptIFrame(ref sanitizer); - break; - default: - PrepareForNone(ref sanitizer); - break; - } - - return level != ESanitizerLevel.All ? sanitizer.Sanitize(html) : html; - } - - /// - /// Очистка всех тегов - /// - /// - private static void PrepareForNone (ref HtmlSanitizer sanitizer) - { + // Выключаю все параметры HTML sanitizer.AllowedTags.Clear(); sanitizer.AllowedSchemes.Clear(); sanitizer.AllowedCssProperties.Clear(); @@ -57,66 +62,146 @@ public static class Sanitizer sanitizer.AllowedAttributes.Clear(); sanitizer.AllowedAtRules.Clear(); sanitizer.AllowDataAttributes = false; + + // Загружаю параметры + sanitizer.AllowedTags.UnionWith(allowedHtml.AllowedTags); + sanitizer.AllowedSchemes.UnionWith(allowedHtml.AllowedSchemes); + sanitizer.AllowedCssProperties.UnionWith(allowedHtml.AllowedCssProperties); + sanitizer.AllowedClasses.UnionWith(allowedHtml.AllowedClasses); + sanitizer.AllowedAttributes.UnionWith(allowedHtml.AllowedAttributes); + sanitizer.AllowDataAttributes = allowedHtml.AllowDataAttributes; + + // Очищаю html согласно правилам + return sanitizer.Sanitize(html); } /// - /// Остаются только текстовые теги + /// Очистка html-кода по уровню очистки /// - /// - private static void PrepareForTextFormatOnly (ref HtmlSanitizer sanitizer) + /// HTML-код + /// Уровень очистка + /// Очищенный html-код + public static string SanitizeHtml(string html, ESanitizerLevel level) { - string[] allowedTags = + // Получаю параметры очистки + SanitizerAllowedHtml allowedHtml = level switch { - "strong", "b", "em", "i", "u", "hr", "strike", "div", "ol", "ul", "li", "p", "span", "h1", "h2", "h3", "h4" - }; - string[] allowedAttributes = - { - "align", "bgcolor", "border", "cellpadding", "cellspacing", "charset", "checked", "class", "clear", "color", "cols", "colspan", - "datetime", "disabled", "headers", "height", "high", "hspace", "label", "lang", "list", "low", "max", "maxlength", "min", "name", - "nowrap", "placeholder", "required", "rev", "rows", "rowspan", "rules", "selected", "size", "span", "spellcheck", "style", "summary", - "tabindex", "title", "type", "valign", "value", "vspace", "width", "wrap" + ESanitizerLevel.NoTags => AllowedNone, + ESanitizerLevel.TextFormatOnly => AllowedTextOnly, + ESanitizerLevel.ImageAndLinks => AllowedImageAndLinks, + ESanitizerLevel.AllExceptIFrame => AllowedAllExceptIFrame, + ESanitizerLevel.All => AllowedAll, + var _ => AllowedAll }; - sanitizer.AllowedTags.Clear(); + // Очищаю код и возвращаю результат очистки + return SanitizeHtml(html, allowedHtml); + } - sanitizer.AllowedTags.UnionWith(allowedTags); + #endregion - sanitizer.AllowedAtRules.Clear(); - sanitizer.AllowDataAttributes = false; + #region Вспомогателдьные методы - sanitizer.AllowedAttributes.Clear(); - sanitizer.AllowedAttributes.UnionWith(allowedAttributes); + /// + /// Получаю параметры, удаляющие все теги + /// + /// Параметры очистки + private static SanitizerAllowedHtml GetNone() => + new() + { + AllowedTags = [], + AllowedAttributes = [], + AllowedCssProperties = [], + AllowedClasses = [], + AllowedSchemes = [], + AllowDataAttributes = false + }; + /// + /// Получаю параметры по умолчанию (разрешающие все теги) + /// + /// Параметры очистки + private static SanitizerAllowedHtml GetAll() + { + // Создаю очиститель + HtmlSanitizer sanitizer = new(); + + // Создаю модель + return new() + { + AllowedTags = sanitizer.AllowedTags.ToList(), + AllowedAttributes = sanitizer.AllowedAttributes.ToList(), + AllowedCssProperties = sanitizer.AllowedCssProperties.ToList(), + AllowedClasses = sanitizer.AllowedClasses.ToList(), + AllowedSchemes = sanitizer.AllowedSchemes.ToList(), + AllowDataAttributes = true + }; } /// - /// Остаются текстовые теги + изображения и ссылки + /// Параметры, оставляющие только текстовые теги /// - /// - private static void PrepareForImageAndLinks (ref HtmlSanitizer sanitizer) + /// Параметры очистки + private static SanitizerAllowedHtml GetTextFormatOnly() => + new() + { + AllowedTags = + [ + "strong", "b", "em", "i", "u", "hr", "strike", "div", "ol", "ul", "li", "p", "span", "h1", "h2", "h3", + "h4" + ], + + // ReSharper disable StringLiteralTypo + AllowedAttributes = + [ + "align", "bgcolor", "border", "cellpadding", "cellspacing", "charset", "checked", "class", "clear", + "color", + "cols", "colspan", "datetime", "disabled", "headers", "height", "high", "hspace", "label", "lang", + "list", + "low", "max", "maxlength", "min", "name", "nowrap", "placeholder", "required", "rev", "rows", "rowspan", + "rules", "selected", "size", "span", "spellcheck", "style", "summary", "tabindex", "title", "type", + "valign", + "value", "vspace", "width", "wrap" + ] + // ReSharper restore StringLiteralTypo + }; + + /// + /// Параметры, оставляющие только текстовые теги, а также img и a + /// + /// Параметры очистки + private static SanitizerAllowedHtml GetImageAndLinks() { - PrepareForTextFormatOnly(ref sanitizer); - string[] allowedTags = - { - "a", "img" - }; + // Получаю текстовые параметры + SanitizerAllowedHtml result = AllowedTextOnly; - string[] allowedAttributes = - { - "alt", "href", "hreflang", "nohref", "rel", "src", "target" - }; + // Добавляю теги + result.AllowedTags.AddRange(["a", "img"]); - sanitizer.AllowedTags.UnionWith(allowedTags); + // Добавляю параметры + // ReSharper disable StringLiteralTypo + result.AllowedAttributes.AddRange(["alt", "href", "hreflang", "nohref", "rel", "src", "target"]); + // ReSharper restore StringLiteralTypo - sanitizer.AllowedAttributes.UnionWith(allowedAttributes); + // Возвращаю результат + return result; } /// - /// Остаются все теги, за исключением IFRAME + /// Применяются все теги, кроме iframe /// - /// - private static void PrepareForAllExceptIFrame (ref HtmlSanitizer sanitizer) + /// Параметры очистки + private static SanitizerAllowedHtml GetAllExceptIFrame() { - sanitizer.AllowedTags.Remove("iframe"); + // Получаю все параметры + SanitizerAllowedHtml result = AllowedAll; + + // Удаляю iframe + result.AllowedTags.Remove("iframe"); + + // Возвращаю результат + return result; } + + #endregion } \ No newline at end of file diff --git a/anbs_cpfn/Classes/SanitizerAllowedHtml.cs b/anbs_cpfn/Classes/SanitizerAllowedHtml.cs new file mode 100644 index 0000000..5a8fbb4 --- /dev/null +++ b/anbs_cpfn/Classes/SanitizerAllowedHtml.cs @@ -0,0 +1,37 @@ +namespace anbs_cp.ForNet.Classes; + +/// +/// Допустимые параметры для очистки HTML +/// +public sealed class SanitizerAllowedHtml +{ + /// + /// Допустимые теги + /// + public List AllowedTags { get; set; } = []; + + /// + /// Допустимые аттрибуты + /// + public List AllowedAttributes { get; set; } = []; + + /// + /// Допустимые параметры css + /// + public List AllowedCssProperties { get; set; } = []; + + /// + /// Допустимые классы + /// + public List AllowedClasses { get; set; } = []; + + /// + /// Допустимые схемы + /// + public List AllowedSchemes { get; set; } = []; + + /// + /// Допустимы ли data-атрибуты + /// + public bool AllowDataAttributes { get; set; } = false; +} \ No newline at end of file diff --git a/anbs_cpfn/anbs_cpfn.csproj b/anbs_cpfn/anbs_cpfn.csproj index 0050b6a..7bfa656 100644 --- a/anbs_cpfn/anbs_cpfn.csproj +++ b/anbs_cpfn/anbs_cpfn.csproj @@ -6,7 +6,7 @@ enable True ANBSoftware.ComponentsPackForNet - 2024.2.24.0 + 2024.3.11.0 Александр Бабаев Набор компонентов ANB Software для ASP.NET Core Библиотека полезных методов языка C# для ASP.NET Core diff --git a/anbs_cpfn/anbs_cpfn.csproj.DotSettings b/anbs_cpfn/anbs_cpfn.csproj.DotSettings deleted file mode 100644 index 632c268..0000000 --- a/anbs_cpfn/anbs_cpfn.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - CSharp120 \ No newline at end of file