V8: Add ability to implement your own HtmlSanitizer (#11897)
* Add IHtmlSanitizer * Use IHtmlSanitizer in RTE value editor * Add docstrings to IHtmlSanitizer * Rename NoOp to Noop To match the rest of the classes * Fix tests
This commit is contained in:
@@ -6,6 +6,7 @@ using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Packaging;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.Core.Telemetry;
|
||||
@@ -81,6 +82,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
new DirectoryInfo(IOHelper.GetRootDirectorySafe())));
|
||||
|
||||
composition.RegisterUnique<ITelemetryService, TelemetryService>();
|
||||
composition.RegisterUnique<IHtmlSanitizer, NoopHtmlSanitizer>();
|
||||
|
||||
return composition;
|
||||
}
|
||||
|
||||
12
src/Umbraco.Core/Security/IHtmlSanitizer.cs
Normal file
12
src/Umbraco.Core/Security/IHtmlSanitizer.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public interface IHtmlSanitizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Sanitizes HTML
|
||||
/// </summary>
|
||||
/// <param name="html">HTML to be sanitized</param>
|
||||
/// <returns>Sanitized HTML</returns>
|
||||
string Sanitize(string html);
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Core/Security/NoopHtmlSanitizer.cs
Normal file
10
src/Umbraco.Core/Security/NoopHtmlSanitizer.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public class NoopHtmlSanitizer : IHtmlSanitizer
|
||||
{
|
||||
public string Sanitize(string html)
|
||||
{
|
||||
return html;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,6 +194,8 @@
|
||||
<Compile Include="PropertyEditors\PropertyCacheCompression.cs" />
|
||||
<Compile Include="PropertyEditors\IPropertyCacheCompression.cs" />
|
||||
<Compile Include="PropertyEditors\UnPublishedContentPropertyCacheCompressionOptions.cs" />
|
||||
<Compile Include="Security\IHtmlSanitizer.cs" />
|
||||
<Compile Include="Security\NoopHtmlSanitizer.cs" />
|
||||
<Compile Include="Serialization\AutoInterningStringConverter.cs" />
|
||||
<Compile Include="Serialization\AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs" />
|
||||
<Compile Include="PropertyEditors\EyeDropperColorPickerConfiguration.cs" />
|
||||
|
||||
@@ -16,6 +16,7 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.Testing;
|
||||
@@ -54,7 +55,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var dataTypeService = new TestObjects.TestDataTypeService(
|
||||
new DataType(new VoidEditor(logger)) { Id = 1 },
|
||||
new DataType(new TrueFalsePropertyEditor(logger)) { Id = 1001 },
|
||||
new DataType(new RichTextPropertyEditor(logger, umbracoContextAccessor, imageSourceParser, linkParser, pastedImages, Mock.Of<IImageUrlGenerator>())) { Id = 1002 },
|
||||
new DataType(new RichTextPropertyEditor(logger, umbracoContextAccessor, imageSourceParser, linkParser, pastedImages, Mock.Of<IImageUrlGenerator>(), Mock.Of<IHtmlSanitizer>())) { Id = 1002 },
|
||||
new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 },
|
||||
new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 },
|
||||
new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 });
|
||||
|
||||
@@ -8,6 +8,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Templates;
|
||||
|
||||
@@ -32,8 +33,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
private readonly RichTextEditorPastedImages _pastedImages;
|
||||
private readonly HtmlLocalLinkParser _localLinkParser;
|
||||
private readonly IImageUrlGenerator _imageUrlGenerator;
|
||||
private readonly IHtmlSanitizer _htmlSanitizer;
|
||||
|
||||
[Obsolete("Use the constructor which takes an IImageUrlGenerator")]
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public GridPropertyEditor(ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
@@ -43,12 +45,24 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public GridPropertyEditor(ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
IImageUrlGenerator imageUrlGenerator)
|
||||
: this(logger, umbracoContextAccessor, imageSourceParser, pastedImages, localLinkParser, imageUrlGenerator, Current.Factory.GetInstance<IHtmlSanitizer>())
|
||||
{
|
||||
}
|
||||
|
||||
public GridPropertyEditor(ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
IImageUrlGenerator imageUrlGenerator,
|
||||
IHtmlSanitizer htmlSanitizer)
|
||||
: base(logger)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
@@ -56,6 +70,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
_pastedImages = pastedImages;
|
||||
_localLinkParser = localLinkParser;
|
||||
_imageUrlGenerator = imageUrlGenerator;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
}
|
||||
|
||||
public override IPropertyIndexValueFactory PropertyIndexValueFactory => new GridPropertyIndexValueFactory();
|
||||
@@ -64,7 +79,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
/// Overridden to ensure that the value is validated
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _umbracoContextAccessor, _imageSourceParser, _pastedImages, _localLinkParser, _imageUrlGenerator);
|
||||
protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _umbracoContextAccessor, _imageSourceParser, _pastedImages, _localLinkParser, _imageUrlGenerator, _htmlSanitizer);
|
||||
|
||||
protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor();
|
||||
|
||||
@@ -77,7 +92,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
private readonly MediaPickerPropertyEditor.MediaPickerPropertyValueEditor _mediaPickerPropertyValueEditor;
|
||||
private readonly IImageUrlGenerator _imageUrlGenerator;
|
||||
|
||||
[Obsolete("Use the constructor which takes an IImageUrlGenerator")]
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public GridPropertyValueEditor(DataEditorAttribute attribute,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
@@ -87,20 +102,32 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public GridPropertyValueEditor(DataEditorAttribute attribute,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
IImageUrlGenerator imageUrlGenerator)
|
||||
: this(attribute, umbracoContextAccessor, imageSourceParser, pastedImages, localLinkParser, imageUrlGenerator, Current.Factory.GetInstance<IHtmlSanitizer>())
|
||||
{
|
||||
}
|
||||
|
||||
public GridPropertyValueEditor(DataEditorAttribute attribute,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
IImageUrlGenerator imageUrlGenerator,
|
||||
IHtmlSanitizer htmlSanitizer)
|
||||
: base(attribute)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_imageSourceParser = imageSourceParser;
|
||||
_pastedImages = pastedImages;
|
||||
_richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, umbracoContextAccessor, imageSourceParser, localLinkParser, pastedImages, _imageUrlGenerator);
|
||||
_mediaPickerPropertyValueEditor = new MediaPickerPropertyEditor.MediaPickerPropertyValueEditor(attribute);
|
||||
_imageUrlGenerator = imageUrlGenerator;
|
||||
_richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, umbracoContextAccessor, imageSourceParser, localLinkParser, pastedImages, _imageUrlGenerator, htmlSanitizer);
|
||||
_mediaPickerPropertyValueEditor = new MediaPickerPropertyEditor.MediaPickerPropertyValueEditor(attribute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Examine;
|
||||
using Umbraco.Web.Macros;
|
||||
@@ -32,21 +33,46 @@ namespace Umbraco.Web.PropertyEditors
|
||||
private readonly HtmlLocalLinkParser _localLinkParser;
|
||||
private readonly RichTextEditorPastedImages _pastedImages;
|
||||
private readonly IImageUrlGenerator _imageUrlGenerator;
|
||||
private readonly IHtmlSanitizer _htmlSanitizer;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The constructor will setup the property editor based on the attribute if one is found
|
||||
/// </summary>
|
||||
[Obsolete("Use the constructor which takes an IImageUrlGenerator")]
|
||||
public RichTextPropertyEditor(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor, HtmlImageSourceParser imageSourceParser, HtmlLocalLinkParser localLinkParser, RichTextEditorPastedImages pastedImages)
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public RichTextPropertyEditor(
|
||||
ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
RichTextEditorPastedImages pastedImages)
|
||||
: this(logger, umbracoContextAccessor, imageSourceParser, localLinkParser, pastedImages, Current.ImageUrlGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor which takes an IHtmlSanitizer")]
|
||||
public RichTextPropertyEditor(
|
||||
ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
IImageUrlGenerator imageUrlGenerator)
|
||||
: this(logger, umbracoContextAccessor, imageSourceParser, localLinkParser, pastedImages, imageUrlGenerator, Current.Factory.GetInstance<IHtmlSanitizer>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor will setup the property editor based on the attribute if one is found
|
||||
/// </summary>
|
||||
public RichTextPropertyEditor(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor, HtmlImageSourceParser imageSourceParser, HtmlLocalLinkParser localLinkParser, RichTextEditorPastedImages pastedImages, IImageUrlGenerator imageUrlGenerator)
|
||||
public RichTextPropertyEditor(
|
||||
ILogger logger,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
IImageUrlGenerator imageUrlGenerator,
|
||||
IHtmlSanitizer htmlSanitizer)
|
||||
: base(logger)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
@@ -54,13 +80,14 @@ namespace Umbraco.Web.PropertyEditors
|
||||
_localLinkParser = localLinkParser;
|
||||
_pastedImages = pastedImages;
|
||||
_imageUrlGenerator = imageUrlGenerator;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a custom value editor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _umbracoContextAccessor, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator);
|
||||
protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _umbracoContextAccessor, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator, _htmlSanitizer);
|
||||
|
||||
protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor();
|
||||
|
||||
@@ -76,8 +103,16 @@ namespace Umbraco.Web.PropertyEditors
|
||||
private readonly HtmlLocalLinkParser _localLinkParser;
|
||||
private readonly RichTextEditorPastedImages _pastedImages;
|
||||
private readonly IImageUrlGenerator _imageUrlGenerator;
|
||||
private readonly IHtmlSanitizer _htmlSanitizer;
|
||||
|
||||
public RichTextPropertyValueEditor(DataEditorAttribute attribute, IUmbracoContextAccessor umbracoContextAccessor, HtmlImageSourceParser imageSourceParser, HtmlLocalLinkParser localLinkParser, RichTextEditorPastedImages pastedImages, IImageUrlGenerator imageUrlGenerator)
|
||||
public RichTextPropertyValueEditor(
|
||||
DataEditorAttribute attribute,
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
HtmlImageSourceParser imageSourceParser,
|
||||
HtmlLocalLinkParser localLinkParser,
|
||||
RichTextEditorPastedImages pastedImages,
|
||||
IImageUrlGenerator imageUrlGenerator,
|
||||
IHtmlSanitizer htmlSanitizer)
|
||||
: base(attribute)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
@@ -85,6 +120,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
_localLinkParser = localLinkParser;
|
||||
_pastedImages = pastedImages;
|
||||
_imageUrlGenerator = imageUrlGenerator;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -141,8 +177,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var parseAndSavedTempImages = _pastedImages.FindAndPersistPastedTempImages(editorValue.Value.ToString(), mediaParentId, userId, _imageUrlGenerator);
|
||||
var editorValueWithMediaUrlsRemoved = _imageSourceParser.RemoveImageSources(parseAndSavedTempImages);
|
||||
var parsed = MacroTagParser.FormatRichTextContentForPersistence(editorValueWithMediaUrlsRemoved);
|
||||
var sanitized = _htmlSanitizer.Sanitize(parsed);
|
||||
|
||||
return parsed.NullOrWhiteSpaceAsNull();
|
||||
return sanitized.NullOrWhiteSpaceAsNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user