Skip to content

Commit

Permalink
Resolve HTML module bug with invalid HTML (#5188)
Browse files Browse the repository at this point in the history
* Add DotNetNuke.Tests.Modules project

* Resolve error with malformed URLs in HTML module

* Refactor and clean-up ManageRelativePaths

Create overload without unused parameter
Give variables more meaningful names
Use StringComparison everywhere possible
  • Loading branch information
bdukes authored Jul 19, 2022
1 parent 6f34381 commit 61bacf0
Show file tree
Hide file tree
Showing 7 changed files with 421 additions and 60 deletions.
120 changes: 63 additions & 57 deletions DNN Platform/Modules/HTML/Components/HtmlTextController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,82 +98,88 @@ public static string FormatHtmlText(int moduleId, string content, HtmlModuleSett
return content;
}

public static string ManageRelativePaths(string strHTML, string strUploadDirectory, string strToken, int intPortalID)
[Obsolete("Deprecated in Platform 9.11.0. Use overload without int. Scheduled removal in v11.0.0.")]
public static string ManageRelativePaths(string htmlContent, string strUploadDirectory, string strToken, int intPortalID)
{
int P = 0;
int R = 0;
int S = 0;
int tLen = 0;
string strURL = null;
return ManageRelativePaths(htmlContent, strUploadDirectory, strToken);
}

public static string ManageRelativePaths(string htmlContent, string uploadDirectory, string token)
{
var htmlContentIndex = 0;
var sbBuff = new StringBuilder(string.Empty);

if (!string.IsNullOrEmpty(strHTML))
if (string.IsNullOrEmpty(htmlContent))
{
tLen = strToken.Length + 2;
string uploadDirectory = strUploadDirectory.ToLowerInvariant();
return string.Empty;
}

// find position of first occurrance:
P = strHTML.IndexOf(strToken + "=\"", StringComparison.InvariantCultureIgnoreCase);
while (P != -1)
{
sbBuff.Append(strHTML.Substring(S, P - S + tLen));
token = token + "=\"";
var tokenLength = token.Length;
uploadDirectory = uploadDirectory.ToLowerInvariant();

// keep charactes left of URL
S = P + tLen;
// find position of first occurrence:
var tokenIndex = htmlContent.IndexOf(token, StringComparison.InvariantCultureIgnoreCase);
while (tokenIndex != -1)
{
sbBuff.Append(htmlContent.Substring(htmlContentIndex, tokenIndex - htmlContentIndex + tokenLength));

// save startpos of URL
R = strHTML.IndexOf("\"", S);
// keep characters left of URL
htmlContentIndex = tokenIndex + tokenLength;

// end of URL
if (R >= 0)
{
strURL = strHTML.Substring(S, R - S).ToLowerInvariant();
}
else
// save start position of URL
var urlEndIndex = htmlContent.IndexOf('\"', htmlContentIndex);

// end of URL
string strURL;
if (urlEndIndex >= 0 && urlEndIndex < htmlContent.Length - 2)
{
strURL = htmlContent.Substring(htmlContentIndex, urlEndIndex - htmlContentIndex).ToLowerInvariant();
}
else
{
tokenIndex = -1;
continue;
}

if (htmlContent.Substring(tokenIndex + tokenLength, 10).Equals("data:image", StringComparison.InvariantCultureIgnoreCase))
{
tokenIndex = htmlContent.IndexOf(token, htmlContentIndex + strURL.Length + 2, StringComparison.InvariantCultureIgnoreCase);
continue;
}

// if we are linking internally
if (!strURL.Contains("://"))
{
// remove the leading portion of the path if the URL contains the upload directory structure
var strDirectory = uploadDirectory;
if (!strDirectory.EndsWith("/", StringComparison.Ordinal))
{
strURL = strHTML.Substring(S).ToLowerInvariant();
strDirectory += "/";
}

if (strHTML.Substring(P + tLen, 10).Equals("data:image", StringComparison.InvariantCultureIgnoreCase))
if (strURL.IndexOf(strDirectory, StringComparison.InvariantCultureIgnoreCase) != -1)
{
P = strHTML.IndexOf(strToken + "=\"", S + strURL.Length + 2, StringComparison.InvariantCultureIgnoreCase);
continue;
htmlContentIndex = htmlContentIndex + strURL.IndexOf(strDirectory, StringComparison.InvariantCultureIgnoreCase) + strDirectory.Length;
strURL = strURL.Substring(strURL.IndexOf(strDirectory, StringComparison.InvariantCultureIgnoreCase) + strDirectory.Length);
}

// if we are linking internally
if (!strURL.Contains("://"))
// add upload directory
// We don't write the UploadDirectory if the token/attribute has not value. Therefore we will avoid an unnecessary request
if (!strURL.StartsWith("/", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(strURL))
{
// remove the leading portion of the path if the URL contains the upload directory structure
string strDirectory = uploadDirectory;
if (!strDirectory.EndsWith("/"))
{
strDirectory += "/";
}

if (strURL.IndexOf(strDirectory) != -1)
{
S = S + strURL.IndexOf(strDirectory) + strDirectory.Length;
strURL = strURL.Substring(strURL.IndexOf(strDirectory) + strDirectory.Length);
}

// add upload directory
if (!strURL.StartsWith("/")
&& !string.IsNullOrEmpty(strURL.Trim())) // We don't write the UploadDirectory if the token/attribute has not value. Therefore we will avoid an unnecessary request
{
sbBuff.Append(uploadDirectory);
}
sbBuff.Append(uploadDirectory);
}

// find position of next occurrance
P = strHTML.IndexOf(strToken + "=\"", S + strURL.Length + 2, StringComparison.InvariantCultureIgnoreCase);
}

if (S > -1)
{
sbBuff.Append(strHTML.Substring(S));
}
// find position of next occurrence
tokenIndex = htmlContent.IndexOf(token, htmlContentIndex + strURL.Length + 2, StringComparison.InvariantCultureIgnoreCase);
}

// append characters of last URL and behind
// append characters of last URL and behind
if (htmlContentIndex > -1)
{
sbBuff.Append(htmlContent.Substring(htmlContentIndex));
}

return sbBuff.ToString();
Expand Down
22 changes: 22 additions & 0 deletions DNN Platform/Tests/DotNetNuke.Tests.Modules/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information

using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DotNetNuke.Library.Tests.Modules")]
[assembly: AssemblyDescription("Open Source Web Application Framework - Test Project")]

[assembly: AssemblyCompany(".NET Foundation")]
[assembly: AssemblyProduct("https://dnncommunity.org")]
[assembly: AssemblyCopyright("DNN Platform is copyright 2002-2022 by .NET Foundation. All Rights Reserved.")]
[assembly: AssemblyTrademark("DNN")]

[assembly: ComVisible(false)]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\NUnit3TestAdapter.4.2.0\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\..\..\packages\NUnit3TestAdapter.4.2.0\build\net35\NUnit3TestAdapter.props')" />
<Import Project="..\..\..\packages\NUnit.3.13.2\build\NUnit.props" Condition="Exists('..\..\..\packages\NUnit.3.13.2\build\NUnit.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EEFFEA77-4FA5-4498-9A9C-1BDBD6436E43}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DotNetNuke.Tests.Modules</RootNamespace>
<AssemblyName>DotNetNuke.Tests.Modules</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>4.0</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<RestorePackages>true</RestorePackages>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<NoWarn>1591, 0618,SA0001</NoWarn>
<LangVersion>7</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<NoWarn>1591, 0618,SA0001</NoWarn>
<LangVersion>7</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Moq">
<HintPath>..\..\..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=3.13.2.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\NUnit.3.13.2\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Html\HtmlTextControllerTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Library\DotNetNuke.Library.csproj">
<Project>{6b29aded-7b56-4484-bea5-c0e09079535b}</Project>
<Name>DotNetNuke.Library</Name>
</ProjectReference>
<ProjectReference Include="..\..\Modules\HTML\DotNetNuke.Modules.Html.csproj">
<Project>{cd8732d8-b4dd-435d-bf21-a90c2964aba4}</Project>
<Name>DotNetNuke.Modules.Html</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\..\stylecop.json">
<Link>stylecop.json</Link>
</AdditionalFiles>
<None Include="..\App.config">
<Link>App.config</Link>
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
<Analyzer Include="..\..\..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
<Error Condition="!Exists('..\..\..\packages\NUnit.3.13.2\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\NUnit.3.13.2\build\NUnit.props'))" />
<Error Condition="!Exists('..\..\..\packages\NUnit3TestAdapter.4.2.0\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\NUnit3TestAdapter.4.2.0\build\net35\NUnit3TestAdapter.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Loading

0 comments on commit 61bacf0

Please sign in to comment.