mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-27 23:19:13 +08:00
Add info bar if blocked elements present in Svg (#1620)
* Added logic to check for blocked elements * Added unit tests * Fix warnings from msi solution
This commit is contained in:
parent
49868d8f7c
commit
d420fad489
@ -384,9 +384,9 @@
|
||||
<!-- File to include common library used by preview handlers -->
|
||||
<File Source="$(var.BinX64Dir)\modules\PreviewHandlerCommon.dll" />
|
||||
<!-- File to include dll for Svg Preview Handler -->
|
||||
<File Id="Svg_PreviewHandler_Dll" Source="$(var.BinX64Dir)\modules\SvgPreviewHandler.dll" />
|
||||
<File Source="$(var.BinX64Dir)\modules\SvgPreviewHandler.dll" />
|
||||
<!-- Files to include dll's for Markdown Preview Handler and it's dependencies -->
|
||||
<File Id="Md_PreviewHandler_Dll" Source="$(var.BinX64Dir)\modules\MarkdownPreviewHandler.dll" />
|
||||
<File Source="$(var.BinX64Dir)\modules\MarkdownPreviewHandler.dll" />
|
||||
<File Source="$(var.BinX64Dir)\modules\Markdig.Signed.dll" />
|
||||
<File Source="$(var.BinX64Dir)\modules\HtmlAgilityPack.dll" />
|
||||
</Component>
|
||||
@ -403,11 +403,11 @@
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Class" Value="SvgPreviewHandler.SvgPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Both" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="CodeBase" Value="file:///[#Svg_PreviewHandler_Dll]" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="CodeBase" Value="file:///[ModulesInstallFolder]SvgPreviewHandler.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Assembly" Value="SvgPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Class" Value="SvgPreviewHandler.SvgPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="RuntimeVersion" Value="v4.0.30319" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="CodeBase" Value="file:///[#Svg_PreviewHandler_Dll]" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="CodeBase" Value="file:///[ModulesInstallFolder]SvgPreviewHandler.dll" />
|
||||
</RegistryKey>
|
||||
<!-- Registry Key for Class Registration of Markdown Preview Handler -->
|
||||
<RegistryKey Root="HKCU" Key="Software\Classes\CLSID\{45769bcc-e8fd-42d0-947e-02beef77a1f5}">
|
||||
@ -420,11 +420,11 @@
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Class" Value="MarkdownPreviewHandler.MarkdownPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Both" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="CodeBase" Value="file:///[#Md_PreviewHandler_Dll]" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="CodeBase" Value="file:///[ModulesInstallFolder]MarkdownPreviewHandler.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Assembly" Value="MarkdownPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Class" Value="MarkdownPreviewHandler.MarkdownPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="RuntimeVersion" Value="v4.0.30319" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="CodeBase" Value="file:///[#Md_PreviewHandler_Dll]" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="CodeBase" Value="file:///[ModulesInstallFolder]MarkdownPreviewHandler.dll" />
|
||||
</RegistryKey>
|
||||
<!-- Registry Key for AppID registration -->
|
||||
<RegistryKey Root="HKCU" Key="Software\Classes\AppID\{CF142243-F059-45AF-8842-DBBE9783DB14}">
|
||||
|
@ -15,6 +15,7 @@ using System.Xml.Linq;
|
||||
using Common;
|
||||
using Common.Utilities;
|
||||
using PreviewHandlerCommon;
|
||||
using SvgPreviewHandler.Utilities;
|
||||
|
||||
namespace SvgPreviewHandler
|
||||
{
|
||||
@ -58,6 +59,13 @@ namespace SvgPreviewHandler
|
||||
}
|
||||
}
|
||||
|
||||
// Add a info bar on top of the Preview if any blocked element is present.
|
||||
if (SvgPreviewHandlerHelper.CheckBlockedElements(svgData))
|
||||
{
|
||||
this.infoBarAdded = true;
|
||||
this.AddTextBoxControl(Resource.BlockedElementInfoText);
|
||||
}
|
||||
|
||||
this.AddBrowserControl(svgData);
|
||||
this.Resize += this.FormResized;
|
||||
base.DoPreview(dataSource);
|
||||
|
@ -107,6 +107,7 @@
|
||||
</Compile>
|
||||
<Compile Include="SvgPreviewHandler.cs" />
|
||||
<Compile Include="SvgTelemetry.cs" />
|
||||
<Compile Include="Utilities\SvgPreviewHandlerHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\common\PreviewHandlerCommon.csproj">
|
||||
|
@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace SvgPreviewHandler.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper utilities for Svg Preview Handler.
|
||||
/// </summary>
|
||||
public class SvgPreviewHandlerHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Dictionary of elements in lower case that are blocked from Svg for preview pane.
|
||||
/// Reference for list of Svg Elements: https://developer.mozilla.org/en-US/docs/Web/SVG/Element.
|
||||
/// </summary>
|
||||
private static Dictionary<string, bool> blockedElementsName = new Dictionary<string, bool>
|
||||
{
|
||||
{ "script", true },
|
||||
{ "image", true },
|
||||
{ "feimage", true },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Check if any of the blocked elements present in Svg.
|
||||
/// </summary>
|
||||
/// <param name="svgData">Input Svg.</param>
|
||||
/// <returns>Returns true in case any of the blocked element is present otherwise false.</returns>
|
||||
public static bool CheckBlockedElements(string svgData)
|
||||
{
|
||||
bool foundBlockedElement = false;
|
||||
if (string.IsNullOrWhiteSpace(svgData))
|
||||
{
|
||||
return foundBlockedElement;
|
||||
}
|
||||
|
||||
// Check if any of the blocked element is present. If failed to parse or iterate over Svg return default false.
|
||||
// No need to throw because all the external content and script are blocked on the Web Browser Control itself.
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Parse(svgData);
|
||||
var elements = doc.Descendants().ToList();
|
||||
foreach (XElement element in elements)
|
||||
{
|
||||
var elementName = element?.Name?.LocalName?.ToLower();
|
||||
if (elementName != null && blockedElementsName.ContainsKey(elementName))
|
||||
{
|
||||
foundBlockedElement = true;
|
||||
|
||||
// No need to iterate further since we are displaying info bar with condition of atleast one occurrence of blocked element is present.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return foundBlockedElement;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
using System;
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -157,6 +161,68 @@ namespace UnitTests_SvgPreviewHandler
|
||||
Assert.AreEqual(finalParentWidth, textBox.Width);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControl_ShouldAddTextBox_IfBlockedElementsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgPreviewControl = new SvgPreviewControl();
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg width =\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
svgBuilder.AppendLine("\t<script>alert(\"hello\")</script>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(RichTextBox));
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[1], typeof(WebBrowserExt));
|
||||
Assert.AreEqual(svgPreviewControl.Controls.Count, 2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControl_ShouldNotAddTextBox_IfNoBlockedElementsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgPreviewControl = new SvgPreviewControl();
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">");
|
||||
svgBuilder.AppendLine("\t<circle cx=\"50\" cy=\"50\" r=\"50\">");
|
||||
svgBuilder.AppendLine("\t</circle>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
|
||||
// Act
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
|
||||
// Assert
|
||||
Assert.IsInstanceOfType(svgPreviewControl.Controls[0], typeof(WebBrowserExt));
|
||||
Assert.AreEqual(svgPreviewControl.Controls.Count, 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SvgPreviewControl_InfoBarWidthShouldAdjustWithParentControlWidthChanges_IfBlockedElementsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgPreviewControl = new SvgPreviewControl();
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg width =\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
svgBuilder.AppendLine("\t<script>alert(\"hello\")</script>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
svgPreviewControl.DoPreview(GetMockStream(svgBuilder.ToString()));
|
||||
var textBox = svgPreviewControl.Controls[0] as RichTextBox;
|
||||
var incrementParentControlWidth = 5;
|
||||
var intialParentWidth = svgPreviewControl.Width;
|
||||
var intitialTextBoxWidth = textBox.Width;
|
||||
var finalParentWidth = intialParentWidth + incrementParentControlWidth;
|
||||
|
||||
// Act
|
||||
svgPreviewControl.Width += incrementParentControlWidth;
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(intialParentWidth, intitialTextBoxWidth);
|
||||
Assert.AreEqual(finalParentWidth, textBox.Width);
|
||||
}
|
||||
|
||||
private IStream GetMockStream(string streamData)
|
||||
{
|
||||
var mockStream = new Mock<IStream>();
|
||||
|
@ -0,0 +1,102 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SvgPreviewHandler.Utilities;
|
||||
using System.Text;
|
||||
|
||||
namespace UnitTests_SvgPreviewHandler
|
||||
{
|
||||
[TestClass]
|
||||
public class SvgPreviewHandlerHelperTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CheckBlockedElements_ShoudReturnTrue_IfABlockedElementIsPresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg width =\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
svgBuilder.AppendLine("\t<script>alert(\"hello\")</script>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
bool foundFilteredElement;
|
||||
|
||||
// Act
|
||||
foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString());
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(foundFilteredElement);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CheckBlockedElements_ShoudReturnTrue_IfBlockedElementsIsPresentInNestedLevel()
|
||||
{
|
||||
// Arrange
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">");
|
||||
svgBuilder.AppendLine("\t<circle cx=\"50\" cy=\"50\" r=\"50\">");
|
||||
svgBuilder.AppendLine("\t\t<script>alert(\"valid-message\")</script>");
|
||||
svgBuilder.AppendLine("\t</circle>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
bool foundFilteredElement;
|
||||
|
||||
// Act
|
||||
foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString());
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(foundFilteredElement);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CheckBlockedElements_ShoudReturnTrue_IfMultipleBlockedElementsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg width =\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
svgBuilder.AppendLine("\t<script>alert(\"valid-message\")</script>");
|
||||
svgBuilder.AppendLine("\t<image href=\"valid-url\" height=\"200\" width=\"200\"/>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
bool foundFilteredElement;
|
||||
|
||||
// Act
|
||||
foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString());
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(foundFilteredElement);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CheckBlockedElements_ShoudReturnFalse_IfNoBlockedElementsArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var svgBuilder = new StringBuilder();
|
||||
svgBuilder.AppendLine("<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">");
|
||||
svgBuilder.AppendLine("\t<circle cx=\"50\" cy=\"50\" r=\"50\">");
|
||||
svgBuilder.AppendLine("\t</circle>");
|
||||
svgBuilder.AppendLine("</svg>");
|
||||
bool foundFilteredElement;
|
||||
|
||||
// Act
|
||||
foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgBuilder.ToString());
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(foundFilteredElement);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
[DataRow(null)]
|
||||
public void CheckBlockedElements_ShoudReturnFalse_IfSvgDataIsNullOrWhiteSpaces(string svgData)
|
||||
{
|
||||
// Arrange
|
||||
bool foundFilteredElement;
|
||||
|
||||
// Act
|
||||
foundFilteredElement = SvgPreviewHandlerHelper.CheckBlockedElements(svgData);
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(foundFilteredElement);
|
||||
}
|
||||
}
|
||||
}
|
@ -89,6 +89,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SvgPreviewControlTests.cs" />
|
||||
<Compile Include="SvgPreviewHandlerHelperTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq">
|
||||
|
Loading…
Reference in New Issue
Block a user