using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text.RegularExpressions; using System.Web; using HtmlAgilityPack; using Kreta.BusinessLogic.Utils; namespace Kreta.BusinessLogic.Logic { public static class RichTextLogic { public static List LegalFastReportHtmlTagList = new List { "br", "b", "i", "u", "sub", "sup" }; public static string[] RemovableHtmlTags = new string[] { "img" }; public static string CutHtmlTagsAndDecode(string input) { string result = HttpUtility.HtmlDecode(input); result = Regex.Replace(result, "<.*?>", string.Empty); return result; } public static string CutHtmlTagsAndDecodeAndBR2Space(string input) { if (!string.IsNullOrWhiteSpace(input)) { string result = HttpUtility.HtmlDecode(input.Replace("
", " ").Replace("
", " ")); result = Regex.Replace(result, "<.*?>", string.Empty); return result; } return input; } public static string RemoveSpecificHtmlTags(string input, string[] htmlTags) { if (string.IsNullOrWhiteSpace(input)) { return input; } var inputHtml = HttpUtility.HtmlDecode(input); foreach (var htmlTag in htmlTags) { inputHtml = Regex.Replace(inputHtml, $"<{htmlTag}" + @"([\w\W]+?)>", string.Empty); } return inputHtml; } public static string ConvertRawHtmlToRichTextHtml(string html) { var actions = new List(); void AddEscapeElementAction(HtmlNode node) { actions.Add(() => node.ParentNode.ReplaceChild(HtmlNode.CreateNode(WebUtility.HtmlEncode(node.OuterHtml)), node)); } void AddRemovePropertyAction(HtmlNode node, HtmlAttribute attr) { actions.Add(() => node.Attributes.Remove(attr)); } void CollectIllegalProperty(HtmlNode node) { var legalAttributes = new List { "style", "href", "target" }; foreach (var item in node.Attributes) { if (!legalAttributes.Contains(item.Name)) { AddRemovePropertyAction(node, item); } } } bool IsLegalItem(HtmlNode node) { var legalItems = new List { "p", "span", "ul", "li", "strong", "del", "ol", "em", "#text", "div", "table", "colgroup", "tr", "td", "th", "tbody", "tfoot", "a", "form", "col", "thead", "head", "br", "strike", "h1", "h2", "h3", "h4", "h5", "h6" }; if (legalItems.Contains(node.Name)) { CollectIllegalProperty(node); return true; } AddEscapeElementAction(node); return false; } void CheckChild(HtmlNode node) { if (node.HasChildNodes) { foreach (var childItem in node.ChildNodes) { if (IsLegalItem(childItem)) { CheckChild(childItem); } } } } var doc = new HtmlDocument(); doc.LoadHtml(WebUtility.HtmlDecode(html)); CheckChild(doc.DocumentNode); foreach (var action in actions) { action.Invoke(); } return doc.DocumentNode.InnerHtml; } public static string GetLegalHtmlString(string text, List legalHtmlTagList, bool mustFastReportCompatible = false, bool enableHtmlTagProperties = false) { while (text.Contains("&")) { text = text.Replace("&", "&"); //NOTE: Replace-elni kell az "&"-okat rekurzívan. } var result = text .Replace("<", "<") //NOTE: Replace-elni kell az "<"-ket, ha valamiért a "<" encode-olva lenne. .Replace(">", ">") //NOTE: Replace-elni kell az ">"-ket, ha valamiért a ">" encode-olva lenne. .Replace(" ", "\u0020") //NOTE: Replace-elni kell az " "-ket. .Replace("\u00A0", "\u0020"); //NOTE: Replace-elni kell a NO-BREAK SPACE-eket, mert a SPACE-el nem ekvivalens és jöhet be ilyen adat és okozhat problémát. if (mustFastReportCompatible) { result = result .Replace("

", "
") //NOTE: A külső div-be írt enter-et ezt generálják ki, ezt replace-eljük
-re. .Replace("

", "
") //NOTE: A kendo editor-ba írt enter-et ezt generálják ki, ezt replace-eljük
-re. .Replace("
", "
") //NOTE: Az összes sortörést egységessé tesszük. .Replace("
", "
") //NOTE: Az összes sortörést egységessé tesszük. .Replace("
", string.Empty) //NOTE: Az összes sortörést egységessé tesszük. .Replace("
", "
") //NOTE: Az összes sortörést egységessé tesszük. .Replace("

", string.Empty) //NOTE: Az összes sortörést egységessé tesszük. .Replace("

", "
") //NOTE: Az összes sortörést egységessé tesszük. .Replace("", "") //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. .Replace("", "") //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. .Replace("", "") //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. .Replace("", "") //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. .Replace("", "") //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. .Replace("", ""); //NOTE: Egységes és FastReport kompatibilis tag-ekre replace-elünk. } //NOTE: --- Start: Replace-eljük az összes nem legális html tag-et. Random random = new Random(); //NOTE: Erre a bonyolult random-ozós replace-es logikára azért van szükség, hogy ne tudják hack-elni véletlenül sem a bejövő adatokat! const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; string closeTagTempString = $"¤{new string(Enumerable.Repeat(chars, 5).Select(s => s[random.Next(s.Length)]).ToArray())}¤"; string openTagTempString = $"÷{new string(Enumerable.Repeat(chars, 5).Select(s => s[random.Next(s.Length)]).ToArray())}÷"; //NOTE: Replace-eljük a legális html tag-eket, hogy azokat a RemoveAllHtmlTags, ne szedje ki! foreach (var legalHtmlTag in legalHtmlTagList) { result = result.Replace($"", $"{closeTagTempString}{legalHtmlTag}{closeTagTempString}") .Replace($"<{legalHtmlTag}>", $"{openTagTempString}{legalHtmlTag}{openTagTempString}"); //NOTE: Ha stílust tartalmaz a legalHtmlTag akkor azt nem szabad leszedni róla (pl szinezés miatt) if (enableHtmlTagProperties) { result = result.Replace($"<{legalHtmlTag}", $"{openTagTempString}{legalHtmlTag}"); } } //NOTE: Replace-eljük az összes html tag-et, ami bennemaradt a szövegben. result = CommonUtils.RemoveAllHtmlTags(result); //NOTE: Vissza Replace-eljük a legális html tag-eket, hogy azok normális formában mentődjenek el! foreach (var legalHtmlTag in legalHtmlTagList) { result = result.Replace($"{closeTagTempString}{legalHtmlTag}{closeTagTempString}", $"") .Replace($"{openTagTempString}{legalHtmlTag}{openTagTempString}", $"<{legalHtmlTag}>"); //NOTE: Ha stílust tartalmaz a legalHtmlTag akkor azt nem szabad leszedni róla (pl szinezés miatt) if (enableHtmlTagProperties) { result = result.Replace($"{openTagTempString}{legalHtmlTag}", $"<{legalHtmlTag}"); } } //NOTE: --- End: Replace-eljük az összes nem legális html tag-et. //NOTE: Remove-oljuk a rossz lezáró tag-eket, amikhez nem tartozik nyitó tag! HtmlDocument htmlDocument = new HtmlDocument(); htmlDocument.LoadHtml(result); List htmlParseErrorList = htmlDocument.ParseErrors.Where(x => x.Code == HtmlParseErrorCode.TagNotOpened).OrderByDescending(x => x.StreamPosition).ToList(); foreach (HtmlParseError htmlParseError in htmlParseErrorList) { result = result.Remove(htmlParseError.StreamPosition, htmlParseError.SourceText.Length); } return result; } /// INFO: Mobil használja public static string RemoveHtmlForMobile(string text) { while (text.Contains("&")) { text = text.Replace("&", "&"); //NOTE: Replace-elni kell az "&"-okat rekurzívan. } var result = text .Replace("<", "<") //NOTE: Replace-elni kell az "<"-ket, ha valamiért a "<" encode-olva lenne. .Replace(">", ">") //NOTE: Replace-elni kell az ">"-ket, ha valamiért a ">" encode-olva lenne. .Replace(" ", "\u0020") //NOTE: Replace-elni kell az " "-ket. .Replace("\u00A0", "\u0020") //NOTE: Replace-elni kell a NO-BREAK SPACE-eket, mert a SPACE-el nem ekvivalens és jöhet be ilyen adat és okozhat problémát. .Replace("

", " ") //NOTE: A külső div-be írt enter-et ezt generálják ki, ezt replace-eljük szóközre. .Replace("

", " ") //NOTE: A kendo editor-ba írt enter-et ezt generálják ki, ezt replace-eljük szóközre. .Replace("
", " ") //NOTE: Az összes sortörést szóközre cseréljük. .Replace("
", " ") //NOTE: Az összes sortörést szóközre cseréljük. .Replace("
", " ") //NOTE: Az összes sortörést szóközre cseréljük. .Replace("", " ") //NOTE: Az összes sortörést szóközre cseréljük. .Replace("

", " ") //NOTE: Az összes sortörést szóközre cseréljük. .Replace("
", string.Empty) //NOTE: Az összes sortörést szóközre cseréljük. .Replace("

", string.Empty) //NOTE: Az összes sortörést szóközre cseréljük. .Replace("", " ") //NOTE: A felsorolás elemeit is elválasztjuk. .Replace("", string.Empty) //NOTE: A formázás tageket töröljük. .Replace("", string.Empty) //NOTE: A formázás tageket töröljük. .Replace("", string.Empty) //NOTE: A formázás tageket töröljük. .Replace("", string.Empty) //NOTE: A formázás tageket töröljük. .Replace("", string.Empty) //NOTE: A formázás tageket töröljük. .Replace("", string.Empty); //NOTE: A formázás tageket töröljük. result = CommonUtils.RemoveAllHtmlTags(result); return HttpUtility.HtmlDecode(result); } } }