diff --git a/DNN Platform/Modules/HTML/Components/HtmlTextController.cs b/DNN Platform/Modules/HTML/Components/HtmlTextController.cs
index 12e9ff1410d..b12161b77f0 100644
--- a/DNN Platform/Modules/HTML/Components/HtmlTextController.cs
+++ b/DNN Platform/Modules/HTML/Components/HtmlTextController.cs
@@ -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();
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Modules/AssemblyInfo.cs b/DNN Platform/Tests/DotNetNuke.Tests.Modules/AssemblyInfo.cs
new file mode 100644
index 00000000000..f067ac87c0c
--- /dev/null
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Modules/AssemblyInfo.cs
@@ -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")]
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Modules/DotNetNuke.Tests.Modules.csproj b/DNN Platform/Tests/DotNetNuke.Tests.Modules/DotNetNuke.Tests.Modules.csproj
new file mode 100644
index 00000000000..d868a9dec1d
--- /dev/null
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Modules/DotNetNuke.Tests.Modules.csproj
@@ -0,0 +1,130 @@
+
+
Hello
", + "/portals/0/", + "src", + 0); + Assert.AreEqual("Hello
", actual); + } + + [Test] + public void ManageRelativePaths_AdjustsRelativeImgSrc() + { + var actual = HtmlTextController.ManageRelativePaths( + "", + "/portals/0/", + "src", + 0); + Assert.AreEqual("", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustImgSrcWithCorrectPathCaseInsensitive() + { + var actual = HtmlTextController.ManageRelativePaths( + "", + "/portals/0/", + "src", + 0); + Assert.AreEqual("", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustImgSrcWithAbsoluteUrl() + { + var actual = HtmlTextController.ManageRelativePaths( + "", + "/portals/0/", + "src", + 0); + Assert.AreEqual("", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustImgSrcWithAbsoluteUrlInContent() + { + var actual = HtmlTextController.ManageRelativePaths( + "src=\"https://example.com/image.jpg\" is how you indicate a URL", + "/portals/0/", + "src", + 0); + Assert.AreEqual("src=\"https://example.com/image.jpg\" is how you indicate a URL", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustContentEndingInImgSrc() + { + var actual = HtmlTextController.ManageRelativePaths( + "src=\"image.jpg\"", + "/portals/0/", + "src", + 0); + Assert.AreEqual("src=\"image.jpg\"", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustContentEndingInUnclosedImgSrc() + { + var actual = HtmlTextController.ManageRelativePaths( + "src=\"image.jpg", + "/portals/0/", + "src", + 0); + Assert.AreEqual("src=\"image.jpg", actual); + } + + [Test] + public void ManageRelativePaths_DoesAdjustImgSrcWithRelativeUrlInContent() + { + // TODO: should we attempt to avoid making this change? + var actual = HtmlTextController.ManageRelativePaths( + "src=\"image.jpg\" is how you indicate a URL", + "/portals/0/", + "src", + 0); + Assert.AreEqual("src=\"/portals/0/image.jpg\" is how you indicate a URL", actual); + } + + [Test] + public void ManageRelativePaths_DoesNotAdjustImgSrcWithDataUrl() + { + var actual = HtmlTextController.ManageRelativePaths( + "", + "/portals/0/", + "src", + 0); + Assert.AreEqual("", actual); + } + + [Test] + public void ManageRelativePaths_AdjustsNonRootedRelativePathsAndDoesNotAdjustOtherPaths() + { + const string HtmlContent = @" + + + + + + + + +"; + var actual = HtmlTextController.ManageRelativePaths( + HtmlContent, + "/portals/0/", + "src", + 0); + + const string Expected = @" + + + + + + + + +"; + Assert.AreEqual(Expected, actual); + } + } +} diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Modules/TestSetup.cs b/DNN Platform/Tests/DotNetNuke.Tests.Modules/TestSetup.cs new file mode 100644 index 00000000000..468db55bb9d --- /dev/null +++ b/DNN Platform/Tests/DotNetNuke.Tests.Modules/TestSetup.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// +using DotNetNuke.Tests.Utilities.Mocks; + +using NUnit.Framework; + +namespace DotNetNuke.Tests.Core +{ + [SetUpFixture] + internal class TestSetup + { + [SetUp] + public void SetUp() + { + } + + [TearDown] + public void TearDown() + { + MockComponentProvider.ResetContainer(); + } + } +} diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Modules/packages.config b/DNN Platform/Tests/DotNetNuke.Tests.Modules/packages.config new file mode 100644 index 00000000000..8e8938b1592 --- /dev/null +++ b/DNN Platform/Tests/DotNetNuke.Tests.Modules/packages.config @@ -0,0 +1,7 @@ + +