From b0374695b15c4532b3dba1e1f62b2075924ba187 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Wed, 26 Sep 2018 21:51:20 +0200 Subject: [PATCH] Fixed udi's rendered in rte content (#2531) --- .../Configuration/UmbracoConfig.cs | 2 +- .../UmbracoSettings/ContentElement.cs | 22 ++++++++--- .../UmbracoSettings/IContentSection.cs | 4 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 3 ++ .../Web/TemplateUtilitiesTests.cs | 37 +++++++++++++++++-- src/Umbraco.Tests/packages.config | 1 + .../Templates/TemplateUtilities.cs | 33 ++++++++++++++++- 7 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Core/Configuration/UmbracoConfig.cs b/src/Umbraco.Core/Configuration/UmbracoConfig.cs index 82d90073e8..5b6d27b9c5 100644 --- a/src/Umbraco.Core/Configuration/UmbracoConfig.cs +++ b/src/Umbraco.Core/Configuration/UmbracoConfig.cs @@ -202,4 +202,4 @@ namespace Umbraco.Core.Configuration //TODO: Add other configurations here ! } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index 17523ab3a1..9fe35f7cb5 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -139,8 +139,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings internal CommaDelimitedConfigurationElement DisallowedUploadFiles { get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); } - } - + } + [ConfigurationProperty("allowedUploadFiles")] internal CommaDelimitedConfigurationElement AllowedUploadFiles { @@ -195,6 +195,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); } } + [ConfigurationProperty("StripUdiAttributes")] + internal InnerTextConfigurationElement StripUdiAttributes + { + get { return GetOptionalTextElement("StripUdiAttributes", true); } + } + string IContentSection.NotificationEmailAddress { get { return Notifications.NotificationEmailAddress; } @@ -313,8 +319,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings IEnumerable IContentSection.DisallowedUploadFiles { get { return DisallowedUploadFiles; } - } - + } + IEnumerable IContentSection.AllowedUploadFiles { get { return AllowedUploadFiles; } @@ -357,7 +363,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings string IContentSection.LoginBackgroundImage { get { return LoginBackgroundImage; } - } - + } + + bool IContentSection.StripUdiAttributes + { + get { return StripUdiAttributes; } + } } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs index d6ee260fa9..6c0d8327f1 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs @@ -75,6 +75,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool EnablePropertyValueConverters { get; } string LoginBackgroundImage { get; } + + bool StripUdiAttributes { get; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 86c36a8d76..abed9b8245 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -65,6 +65,9 @@ ..\packages\Examine.0.1.89\lib\net45\Examine.dll + + ..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll + ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index f2a04c5f0f..96461519d8 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Web; +using HtmlAgilityPack; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -10,7 +10,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Profiling; using Umbraco.Core.Scoping; -using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Web.Routing; @@ -34,6 +33,14 @@ namespace Umbraco.Tests.Web [TestCase("hello href=\"{localLink:umb://document-type/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")] //this one has an invalid char so won't match [TestCase("hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")] + // with a-tag with data-udi attribute, that needs to be stripped + [TestCase("hello world ", "hello world ")] + // with a-tag with data-udi attribute spelled wrong, so don't need stripping + [TestCase("hello world ", "hello world ")] + // with a img-tag with data-udi id, that needs to be strippde + [TestCase("hello world ", "hello world ")] + // with a img-tag with data-udi id spelled wrong, so don't need stripping + [TestCase("hello world ", "hello world ")] public void ParseLocalLinks(string input, string result) { var serviceCtxMock = MockHelper.GetMockedServiceContext(); @@ -63,7 +70,7 @@ namespace Umbraco.Tests.Web //setup a quick mock of the WebRouting section Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == "AutoLegacy")), //pass in the custom url provider - new[]{ testUrlProvider.Object }, + new[] { testUrlProvider.Object }, true)) { var output = TemplateUtilities.ParseInternalLinks(input, umbCtx.UrlProvider); @@ -71,5 +78,27 @@ namespace Umbraco.Tests.Web Assert.AreEqual(result, output); } } + + [Test] + public void StripDataUdiAttributesUsingSrtringOnLinks() + { + var input = "hello world "; + var expected = "hello world "; + + var result = TemplateUtilities.StripUdiDataAttributes(input); + + Assert.AreEqual(expected, result); + } + + [Test] + public void StripDataUdiAttributesUsingStringOnImages() + { + var input = "hello world "; + var expected = "hello world "; + + var result = TemplateUtilities.StripUdiDataAttributes(input); + + Assert.AreEqual(expected, result); + } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index 45afd3279c..e458795917 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -3,6 +3,7 @@ + diff --git a/src/Umbraco.Web/Templates/TemplateUtilities.cs b/src/Umbraco.Web/Templates/TemplateUtilities.cs index a7e6738374..39ac69989a 100644 --- a/src/Umbraco.Web/Templates/TemplateUtilities.cs +++ b/src/Umbraco.Web/Templates/TemplateUtilities.cs @@ -1,4 +1,6 @@ -using System; +using HtmlAgilityPack; +using System; +using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -46,6 +48,11 @@ namespace Umbraco.Web.Templates { if (urlProvider == null) throw new ArgumentNullException("urlProvider"); + if(string.IsNullOrEmpty(text)) + { + return text; + } + // Parse internal links var tags = LocalLinkPattern.Matches(text); foreach (Match tag in tags) @@ -74,6 +81,11 @@ namespace Umbraco.Web.Templates } } + if (UmbracoConfig.For.UmbracoSettings().Content.StripUdiAttributes) + { + text = StripUdiDataAttributes(text); + } + return text; } @@ -102,6 +114,9 @@ namespace Umbraco.Web.Templates private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + private static readonly Regex UdiDataAttributePattern = new Regex("data-udi=\"[^\\\"]*\"", + RegexOptions.IgnoreCase | RegexOptions.Compiled); + /// /// The RegEx matches any HTML attribute values that start with a tilde (~), those that match are passed to ResolveUrl to replace the tilde with the application path. /// @@ -145,5 +160,21 @@ namespace Umbraco.Web.Templates { return text.CleanForXss(ignoreFromClean); } + + /// + /// Strips data-udi attributes from rich text + /// + /// A html string + /// A string stripped from the data-uid attributes + public static string StripUdiDataAttributes(string input) + { + if (string.IsNullOrEmpty(input)) + { + return string.Empty; + } + + + return UdiDataAttributePattern.Replace(input, string.Empty); + } } }