diff --git a/Build/Build.csproj b/Build/Build.csproj
index 40c6b91c322..bf0e19cd734 100644
--- a/Build/Build.csproj
+++ b/Build/Build.csproj
@@ -1,33 +1,33 @@
-
-
- Exe
- net8.0
- true
-
- $(MSBuildProjectDirectory)
- DotNetNuke.Build
- true
- CS0618
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
+
+
+ Exe
+ net8.0
+ true
+
+ $(MSBuildProjectDirectory)
+ DotNetNuke.Build
+ true
+ CS0618
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/DNN Platform/Library/Common/Utilities/UrlUtils.cs b/DNN Platform/Library/Common/Utilities/UrlUtils.cs
index 0c36255ecd2..bb399433a09 100644
--- a/DNN Platform/Library/Common/Utilities/UrlUtils.cs
+++ b/DNN Platform/Library/Common/Utilities/UrlUtils.cs
@@ -4,6 +4,7 @@
namespace DotNetNuke.Common.Utilities
{
using System;
+ using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
@@ -17,10 +18,15 @@ namespace DotNetNuke.Common.Utilities
using DotNetNuke.Security;
using Microsoft.Extensions.DependencyInjection;
- public class UrlUtils
+ /// Provides utilities for dealing with DNN's URLs. Consider using if applicable.
+ public static class UrlUtils
{
private static readonly INavigationManager NavigationManager = Globals.DependencyProvider.GetRequiredService();
+ /// Combines two URLs, trimming any slashes between them.
+ /// The base URL.
+ /// The URL to add to the base URL.
+ /// A new URL that combines and .
public static string Combine(string baseUrl, string relativeUrl)
{
if (baseUrl.Length == 0)
@@ -33,75 +39,106 @@ public static string Combine(string baseUrl, string relativeUrl)
return baseUrl;
}
- return string.Format("{0}/{1}", baseUrl.TrimEnd(new[] { '/', '\\' }), relativeUrl.TrimStart(new[] { '/', '\\' }));
+ baseUrl = baseUrl.TrimEnd('/', '\\');
+ relativeUrl = relativeUrl.TrimStart('/', '\\');
+ return $"{baseUrl}/{relativeUrl}";
}
+ /// Decodes a base64 encoded value generated via .
+ /// The encoded value.
+ /// The decoded value.
public static string DecodeParameter(string value)
{
- value = value.Replace("-", "+").Replace("_", "/").Replace("$", "=");
+ value = value.Replace('-', '+').Replace('_', '/').Replace('$', '=');
byte[] arrBytes = Convert.FromBase64String(value);
return Encoding.UTF8.GetString(arrBytes);
}
+ /// Decrypts an encrypted value generated via . Decrypted using the current portal's .
+ /// The encrypted value.
+ /// The decrypted value.
public static string DecryptParameter(string value)
{
return DecryptParameter(value, PortalController.Instance.GetCurrentSettings().GUID.ToString());
}
+ /// Decrypts an encrypted value generated via .
+ /// The encrypted value.
+ /// The key used to encrypt the value.
+ /// The decrypted value.
public static string DecryptParameter(string value, string encryptionKey)
{
- var objSecurity = PortalSecurity.Instance;
-
// [DNN-8257] - Can't do URLEncode/URLDecode as it introduces issues on decryption (with / = %2f), so we use a modified Base64
var toDecrypt = new StringBuilder(value);
- toDecrypt.Replace("_", "/");
- toDecrypt.Replace("-", "+");
+ toDecrypt.Replace('_', '/');
+ toDecrypt.Replace('-', '+');
toDecrypt.Replace("%3d", "=");
- return objSecurity.Decrypt(encryptionKey, toDecrypt.ToString());
+ return PortalSecurity.Instance.Decrypt(encryptionKey, toDecrypt.ToString());
}
+ /// Encodes a value (using base64) for placing in a URL.
+ /// The value to encode.
+ /// The encoded value.
public static string EncodeParameter(string value)
{
byte[] arrBytes = Encoding.UTF8.GetBytes(value);
var toEncode = new StringBuilder(Convert.ToBase64String(arrBytes));
- toEncode.Replace("+", "-");
- toEncode.Replace("/", "_");
- toEncode.Replace("=", "$");
+ toEncode.Replace('+', '-');
+ toEncode.Replace('/', '_');
+ toEncode.Replace('=', '$');
return toEncode.ToString();
}
+ /// Encrypt a parameter for placing in a URL. Encrypted using the current portal's .
+ /// The value to encrypt.
+ /// The encrypted value.
public static string EncryptParameter(string value)
{
return EncryptParameter(value, PortalController.Instance.GetCurrentSettings().GUID.ToString());
}
+ /// Encrypt a parameter for placing in a URL.
+ /// The value to encrypt.
+ /// The key to use when encrypting the value. This key must be used to decrypt the value.
+ /// The encrypted value.
public static string EncryptParameter(string value, string encryptionKey)
{
- var objSecurity = PortalSecurity.Instance;
- var parameterValue = new StringBuilder(objSecurity.Encrypt(encryptionKey, value));
+ var encryptedValue = PortalSecurity.Instance.Encrypt(encryptionKey, value);
+ var parameterValue = new StringBuilder(encryptedValue);
// [DNN-8257] - Can't do URLEncode/URLDecode as it introduces issues on decryption (with / = %2f), so we use a modified Base64
- parameterValue.Replace("/", "_");
- parameterValue.Replace("+", "-");
+ parameterValue.Replace('/', '_');
+ parameterValue.Replace('+', '-');
parameterValue.Replace("=", "%3d");
return parameterValue.ToString();
}
+ /// Gets the name from a query string pair.
+ /// The pair, e.g. "name=value".
+ /// The name.
public static string GetParameterName(string pair)
{
- string[] nameValues = pair.Split('=');
- return nameValues[0];
+ var length = pair.IndexOf('=');
+ if (length == -1)
+ {
+ length = pair.Length;
+ }
+
+ return pair.Substring(0, length);
}
+ /// Gets the value from a query string pair.
+ /// The pair, e.g. "name=value".
+ /// The value.
public static string GetParameterValue(string pair)
{
- string[] nameValues = pair.Split('=');
- if (nameValues.Length > 1)
+ var start = pair.IndexOf('=') + 1;
+ if (start == 0)
{
- return nameValues[1];
+ return string.Empty;
}
- return string.Empty;
+ return pair.Substring(start);
}
///
@@ -270,44 +307,57 @@ public static string PopUpUrl(string url, Control control, PortalSettings portal
return popUpUrl;
}
+ /// Creates a URL (or script) to close a pop-up.
+ /// Whether to refresh the page when the pop-up is closed.
+ /// The URL.
+ /// Whether to generate a script for an onClick event (rather than a URL with a javascript: protocol).
+ /// The URL or script.
public static string ClosePopUp(bool refresh, string url, bool onClickEvent)
{
- var closePopUpStr = "dnnModal.closePopUp({0}, {1})";
- closePopUpStr = "javascript:" + string.Format(closePopUpStr, refresh.ToString().ToLowerInvariant(), "'" + url + "'");
-
- // Removes the javascript txt for onClick scripts)
- if (onClickEvent && closePopUpStr.StartsWith("javascript:"))
- {
- closePopUpStr = closePopUpStr.Replace("javascript:", string.Empty);
- }
-
- return closePopUpStr;
+ var protocol = onClickEvent ? string.Empty : "javascript:";
+ var refreshBool = refresh.ToString().ToLowerInvariant();
+ var urlString = HttpUtility.JavaScriptStringEncode(url, addDoubleQuotes: true);
+ return $"{protocol}dnnModal.closePopUp({refreshBool}, {urlString})";
}
+ /// Replaces a query string parameter's value in a URL.
+ /// The URL.
+ /// The parameter name.
+ /// The parameter value.
+ /// The updated URL.
public static string ReplaceQSParam(string url, string param, string newValue)
{
if (Host.UseFriendlyUrls)
{
- return Regex.Replace(url, "(.*)(" + param + "/)([^/]+)(/.*)", "$1$2" + newValue + "$4", RegexOptions.IgnoreCase);
+ var escapedReplacementValue = newValue.Replace("$1", "$$1").Replace("$2", "$$2").Replace("$3", "$$3").Replace("$4", "$$4");
+ return Regex.Replace(url, $@"(.*)({Regex.Escape(param)}/)([^/]+)(/.*)", $"$1$2{escapedReplacementValue}$4", RegexOptions.IgnoreCase);
}
else
{
- return Regex.Replace(url, "(.*)(&|\\?)(" + param + "=)([^&\\?]+)(.*)", "$1$2$3" + newValue + "$5", RegexOptions.IgnoreCase);
+ var escapedReplacementValue = newValue.Replace("$1", "$$1").Replace("$2", "$$2").Replace("$3", "$$3").Replace("$4", "$$4").Replace("$5", "$$5");
+ return Regex.Replace(url, $@"(.*)(&|\?)({Regex.Escape(param)}=)([^&\?]+)(.*)", $"$1$2$3{escapedReplacementValue}$5", RegexOptions.IgnoreCase);
}
}
+ /// Removes the query string parameter with the given name from the URL.
+ /// The URL.
+ /// The parameter name.
+ /// The updated URL.
public static string StripQSParam(string url, string param)
{
if (Host.UseFriendlyUrls)
{
- return Regex.Replace(url, "(.*)(" + param + "/[^/]+/)(.*)", "$1$3", RegexOptions.IgnoreCase);
+ return Regex.Replace(url, $"(.*)({Regex.Escape(param)}/[^/]+/)(.*)", "$1$3", RegexOptions.IgnoreCase);
}
else
{
- return Regex.Replace(url, "(.*)(&|\\?)(" + param + "=)([^&\\?]+)([&\\?])?(.*)", "$1$2$6", RegexOptions.IgnoreCase).Replace("(.*)([&\\?]$)", "$1");
+ return Regex.Replace(url, $@"(.*)(&|\?)({Regex.Escape(param)}=)([^&\?]+)([&\?])?(.*)", "$1$2$6", RegexOptions.IgnoreCase).Replace("(.*)([&\\?]$)", "$1");
}
}
+ /// Determines whether a is valid as a return URL.
+ /// The URL string.
+ /// The normalized return URL or .
public static string ValidReturnUrl(string url)
{
try
@@ -318,8 +368,8 @@ public static string ValidReturnUrl(string url)
return url;
}
- url = url.Replace("\\", "/");
- if (url.ToLowerInvariant().Contains("data:"))
+ url = url.Replace('\\', '/');
+ if (url.IndexOf("data:", StringComparison.OrdinalIgnoreCase) > -1)
{
return string.Empty;
}
@@ -333,12 +383,12 @@ public static string ValidReturnUrl(string url)
// redirect url should never contain a protocol ( if it does, it is likely a cross-site request forgery attempt )
var urlWithNoQuery = url;
- if (urlWithNoQuery.Contains("?"))
+ if (urlWithNoQuery.IndexOf('?') > -1)
{
urlWithNoQuery = urlWithNoQuery.Substring(0, urlWithNoQuery.IndexOf("?", StringComparison.InvariantCultureIgnoreCase));
}
- if (urlWithNoQuery.Contains("://"))
+ if (urlWithNoQuery.IndexOf(':') > -1)
{
var portalSettings = PortalSettings.Current;
var aliasWithHttp = Globals.AddHTTP(((IPortalAliasInfo)portalSettings.PortalAlias).HttpAlias);
@@ -358,12 +408,12 @@ public static string ValidReturnUrl(string url)
}
}
- while (url.StartsWith("///"))
+ while (url.StartsWith("///", StringComparison.Ordinal))
{
url = url.Substring(1);
}
- if (url.StartsWith("//"))
+ if (url.StartsWith("//", StringComparison.Ordinal))
{
var urlWithNoProtocol = url.Substring(2);
var portalSettings = PortalSettings.Current;
@@ -383,20 +433,24 @@ public static string ValidReturnUrl(string url)
}
}
- // Whether current page is show in popup.
+ /// Determines whether the current page is being shown in a pop-up.
+ /// if the current page is in a pop-up, otherwise .
public static bool InPopUp()
{
- return HttpContext.Current != null && HttpContext.Current.Request.Url.ToString().IndexOf("popUp=true", StringComparison.OrdinalIgnoreCase) >= 0;
+ return HttpContext.Current != null && IsPopUp(HttpContext.Current.Request.Url.ToString());
}
+ /// Determines whether the given URL is for a page being shown in a pop-up.
+ /// The URL.
+ /// if the URL is for a page in a pop-up, otherwise .
public static bool IsPopUp(string url)
{
return url.IndexOf("popUp=true", StringComparison.OrdinalIgnoreCase) >= 0;
}
/// Redirect current response to 404 error page or output 404 content if error page not defined.
- ///
- ///
+ /// The response.
+ /// The portal settings.
public static void Handle404Exception(HttpResponse response, PortalSettings portalSetting)
{
if (portalSetting?.ErrorPage404 > Null.NullInteger)
diff --git a/DNN Platform/Library/Services/FileSystem/FileManager.cs b/DNN Platform/Library/Services/FileSystem/FileManager.cs
index da11b4c4847..e38369b9fa6 100644
--- a/DNN Platform/Library/Services/FileSystem/FileManager.cs
+++ b/DNN Platform/Library/Services/FileSystem/FileManager.cs
@@ -211,7 +211,7 @@ public virtual IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fil
usingSeekableStream = true;
}
- this.CheckFileWritingRestrictions(folder, fileName, fileContent, oldFile, createdByUserID);
+ this.CheckFileWritingRestrictions(folder, fileName, fileContent, oldFile, createdByUserID, ignoreWhiteList);
// Retrieve Metadata
this.SetInitialFileMetadata(ref fileContent, file, folderProvider);
@@ -1823,7 +1823,7 @@ private void SetImageProperties(IFileInfo file, Stream fileContent)
}
}
- private void CheckFileWritingRestrictions(IFolderInfo folder, string fileName, Stream fileContent, IFileInfo oldFile, int createdByUserId)
+ private void CheckFileWritingRestrictions(IFolderInfo folder, string fileName, Stream fileContent, IFileInfo oldFile, int createdByUserId, bool ignoreWhiteList)
{
if (!PortalController.Instance.HasSpaceAvailable(folder.PortalID, fileContent.Length))
{
@@ -1848,6 +1848,14 @@ private void CheckFileWritingRestrictions(IFolderInfo folder, string fileName, S
var errorMessage = Localization.GetExceptionMessage("AddFileInvalidContent", defaultMessage);
throw new InvalidFileContentException(string.Format(errorMessage, fileName));
}
+
+ var checkWhiteList = !(UserController.Instance.GetCurrentUserInfo().IsSuperUser && ignoreWhiteList);
+ if (checkWhiteList && !this.WhiteList.IsAllowedExtension(".exe") && !FileSecurityController.Instance.ValidateNotExectuable(fileContent))
+ {
+ var defaultMessage = "The content of '{0}' is not valid. The file has not been added.";
+ var errorMessage = Localization.GetExceptionMessage("AddFileInvalidContent", defaultMessage);
+ throw new InvalidFileContentException(string.Format(errorMessage, fileName));
+ }
}
private void ManageFileAdding(int createdByUserID, Workflow folderWorkflow, bool fileExists, FileInfo file)
diff --git a/DNN Platform/Library/Services/FileSystem/Internal/FileSecurityController.cs b/DNN Platform/Library/Services/FileSystem/Internal/FileSecurityController.cs
index 5f99d054a0d..e216ac69d04 100644
--- a/DNN Platform/Library/Services/FileSystem/Internal/FileSecurityController.cs
+++ b/DNN Platform/Library/Services/FileSystem/Internal/FileSecurityController.cs
@@ -41,6 +41,19 @@ public bool Validate(string fileName, Stream fileContent)
}
}
+ ///
+ public bool ValidateNotExectuable(Stream fileContent)
+ {
+ Requires.NotNull("fileContent", fileContent);
+
+ var firstBytes = new byte[2];
+ int bytesRead = fileContent.Read(firstBytes, 0, 2);
+ fileContent.Position = 0;
+
+ // Windows exectuable files start with 0x4D 0x5A
+ return bytesRead < 2 || firstBytes[0] != 0x4D || firstBytes[1] != 0x5A;
+ }
+
///
protected override Func GetFactory()
{
diff --git a/DNN Platform/Library/Services/FileSystem/Internal/IFileSecurityController.cs b/DNN Platform/Library/Services/FileSystem/Internal/IFileSecurityController.cs
index 3cd55c767ab..6a52d4ba794 100644
--- a/DNN Platform/Library/Services/FileSystem/Internal/IFileSecurityController.cs
+++ b/DNN Platform/Library/Services/FileSystem/Internal/IFileSecurityController.cs
@@ -13,5 +13,12 @@ public interface IFileSecurityController
/// The File Content.
/// if the file has valid content, otherwise .
bool Validate(string fileName, Stream fileContent);
+
+ ///
+ /// Checks the file content isn't an exectuable file.
+ ///
+ /// The File Content.
+ /// Whether the file is an exectuable file.
+ bool ValidateNotExectuable(Stream fileContent);
}
}
diff --git a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx
index 1d1851172a5..277736c9b09 100644
--- a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx
+++ b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx
@@ -435,4 +435,7 @@
{0} Assets
+
+ Open
+
\ No newline at end of file
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts
index b0449927cf3..91058ceba56 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts
@@ -26,6 +26,9 @@ export namespace Components {
interface DnnActionMoveItems {
"items": Item[];
}
+ interface DnnActionOpenFile {
+ "item": Item;
+ }
interface DnnActionUnlinkItems {
"items": Item[];
}
@@ -252,6 +255,12 @@ declare global {
prototype: HTMLDnnActionMoveItemsElement;
new (): HTMLDnnActionMoveItemsElement;
};
+ interface HTMLDnnActionOpenFileElement extends Components.DnnActionOpenFile, HTMLStencilElement {
+ }
+ var HTMLDnnActionOpenFileElement: {
+ prototype: HTMLDnnActionOpenFileElement;
+ new (): HTMLDnnActionOpenFileElement;
+ };
interface HTMLDnnActionUnlinkItemsElement extends Components.DnnActionUnlinkItems, HTMLStencilElement {
}
var HTMLDnnActionUnlinkItemsElement: {
@@ -409,6 +418,7 @@ declare global {
"dnn-action-download-item": HTMLDnnActionDownloadItemElement;
"dnn-action-edit-item": HTMLDnnActionEditItemElement;
"dnn-action-move-items": HTMLDnnActionMoveItemsElement;
+ "dnn-action-open-file": HTMLDnnActionOpenFileElement;
"dnn-action-unlink-items": HTMLDnnActionUnlinkItemsElement;
"dnn-action-upload-file": HTMLDnnActionUploadFileElement;
"dnn-resource-manager": HTMLDnnResourceManagerElement;
@@ -455,6 +465,9 @@ declare namespace LocalJSX {
interface DnnActionMoveItems {
"items": Item[];
}
+ interface DnnActionOpenFile {
+ "item": Item;
+ }
interface DnnActionUnlinkItems {
"items": Item[];
}
@@ -570,6 +583,10 @@ declare namespace LocalJSX {
* The list of current items.
*/
"currentItems": GetFolderContentResponse;
+ /**
+ * Fires when a file is double-clicked and emits the file ID into the event.detail
+ */
+ "onDnnRmFileDoubleClicked"?: (event: DnnRmItemsCardviewCustomEvent) => void;
/**
* Fires when a folder is double-clicked and emits the folder ID into the event.detail
*/
@@ -580,6 +597,10 @@ declare namespace LocalJSX {
* The list of current items.
*/
"currentItems": GetFolderContentResponse;
+ /**
+ * Fires when a file is double-clicked and emits the file ID into the event.detail
+ */
+ "onDnnRmFileDoubleClicked"?: (event: DnnRmItemsListviewCustomEvent) => void;
/**
* Fires when a folder is double-clicked and emits the folder ID into the event.detail
*/
@@ -658,6 +679,7 @@ declare namespace LocalJSX {
"dnn-action-download-item": DnnActionDownloadItem;
"dnn-action-edit-item": DnnActionEditItem;
"dnn-action-move-items": DnnActionMoveItems;
+ "dnn-action-open-file": DnnActionOpenFile;
"dnn-action-unlink-items": DnnActionUnlinkItems;
"dnn-action-upload-file": DnnActionUploadFile;
"dnn-resource-manager": DnnResourceManager;
@@ -695,6 +717,7 @@ declare module "@stencil/core" {
"dnn-action-download-item": LocalJSX.DnnActionDownloadItem & JSXBase.HTMLAttributes;
"dnn-action-edit-item": LocalJSX.DnnActionEditItem & JSXBase.HTMLAttributes;
"dnn-action-move-items": LocalJSX.DnnActionMoveItems & JSXBase.HTMLAttributes;
+ "dnn-action-open-file": LocalJSX.DnnActionOpenFile & JSXBase.HTMLAttributes;
"dnn-action-unlink-items": LocalJSX.DnnActionUnlinkItems & JSXBase.HTMLAttributes;
"dnn-action-upload-file": LocalJSX.DnnActionUploadFile & JSXBase.HTMLAttributes;
"dnn-resource-manager": LocalJSX.DnnResourceManager & JSXBase.HTMLAttributes;
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-open-file/dnn-action-open-file.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-open-file/dnn-action-open-file.tsx
new file mode 100644
index 00000000000..c3876118317
--- /dev/null
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-open-file/dnn-action-open-file.tsx
@@ -0,0 +1,29 @@
+import { Component, Host, h, Prop } from '@stencil/core';
+import { Item } from '../../../services/ItemsClient';
+import state from "../../../store/store";
+
+@Component({
+ tag: 'dnn-action-open-file',
+ styleUrl: '../dnn-action.scss',
+ shadow: true,
+})
+export class DnnActionOpenFile {
+
+ @Prop() item!: Item;
+
+
+ private handleClick(): void {
+ window.open(this.item.path, "_blank");
+ }
+
+ render() {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-file-context-menu/dnn-rm-file-context-menu.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-file-context-menu/dnn-rm-file-context-menu.tsx
index 80276d1075a..0cc180416e2 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-file-context-menu/dnn-rm-file-context-menu.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-file-context-menu/dnn-rm-file-context-menu.tsx
@@ -23,6 +23,8 @@ export class DnnRmFileContextMenu {
,
+ ,
+
,
]
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx
index 7ba42d25cc2..e1ac47ef275 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx
@@ -123,6 +123,9 @@ export class DnnRmActionsBar {
{state.selectedItems.length == 1 && !state.selectedItems[0].isFolder && location.protocol == "https:" &&
}
+ {state.selectedItems.length == 1 && !state.selectedItems[0].isFolder &&
+
+ }
{state.selectedItems.length == 1 && !state.selectedItems[0].isFolder &&
}
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx
index 34a5a7e34b4..ae0bdcd6b47 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx
@@ -37,6 +37,11 @@ export class DnnRmFilesPane {
this.checkIfMoreItemsNeeded();
}
+ @Listen("dnnRmFileDoubleClicked", {target: "document"})
+ handleFileDoubleClicked(e: CustomEvent) {
+ window.open(e.detail, "_blank");
+ }
+
componentDidUpdate() {
const loadedFilesHeight = this.loadedFilesArea.getBoundingClientRect().height;
const heightPerItem = loadedFilesHeight / state.currentItems.items.length;
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx
index e48f9495bda..e97ea57d0b4 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx
@@ -18,6 +18,9 @@ export class DnnRmItemsCardview {
/** Fires when a folder is double-clicked and emits the folder ID into the event.detail */
@Event() dnnRmFolderDoubleClicked: EventEmitter;
+ /** Fires when a file is double-clicked and emits the file ID into the event.detail */
+ @Event() dnnRmFileDoubleClicked: EventEmitter;
+
componentWillLoad() {
document.addEventListener("click", this.dismissContextMenu.bind(this));
}
@@ -54,6 +57,8 @@ export class DnnRmItemsCardview {
private handleDoubleClick(item: Item): void {
if (item.isFolder) {
this.dnnRmFolderDoubleClicked.emit(item.itemId);
+ } else {
+ this.dnnRmFileDoubleClicked.emit(item.path);
}
}
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx
index 30d0fb813b1..e5a5779598f 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx
@@ -18,6 +18,9 @@ export class DnnRmItemsListview {
/** Fires when a folder is double-clicked and emits the folder ID into the event.detail */
@Event() dnnRmFolderDoubleClicked: EventEmitter;
+ /** Fires when a file is double-clicked and emits the file ID into the event.detail */
+ @Event() dnnRmFileDoubleClicked: EventEmitter;
+
componentWillLoad() {
document.addEventListener("click", this.dismissContextMenu.bind(this));
}
@@ -85,6 +88,8 @@ export class DnnRmItemsListview {
private handleDoubleClick(item: Item): void {
if (item.isFolder) {
this.dnnRmFolderDoubleClicked.emit(item.itemId);
+ } else {
+ this.dnnRmFileDoubleClicked.emit(item.path);
}
}
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/dnn-rm-left-pane.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/dnn-rm-left-pane.tsx
index 31238f5c549..23c6d9dda00 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/dnn-rm-left-pane.tsx
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/dnn-rm-left-pane.tsx
@@ -17,6 +17,7 @@ export class DnnRmLeftPane {
}
private handleFolderClicked(e: CustomEvent): void {
+ state.selectedItems = [];
this.itemsClient.getFolderContent(
Number.parseInt(e.detail.data.key),
0,
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts
index ff27978c2fc..93160a4307f 100644
--- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts
+++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts
@@ -142,6 +142,7 @@ export interface LocalizedStrings {
Unlink: string;
CopyUrl: string;
StatusBarMessage: string;
+ OpenFile: string;
Download: string;
Upload: string;
};
\ No newline at end of file
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/Common/UrlUtilsTests.cs b/DNN Platform/Tests/DotNetNuke.Tests.Core/Common/UrlUtilsTests.cs
new file mode 100644
index 00000000000..fde0822bcdc
--- /dev/null
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/Common/UrlUtilsTests.cs
@@ -0,0 +1,327 @@
+// 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
+
+namespace DotNetNuke.Tests.Core.Common;
+
+using System;
+using System.Collections.Generic;
+using System.Web.Caching;
+using DotNetNuke.Abstractions;
+using DotNetNuke.Abstractions.Application;
+using DotNetNuke.Abstractions.Portals;
+using DotNetNuke.Abstractions.Settings;
+using DotNetNuke.Common;
+using DotNetNuke.Common.Utilities;
+using DotNetNuke.ComponentModel;
+using DotNetNuke.Entities;
+using DotNetNuke.Entities.Controllers;
+using DotNetNuke.Entities.Portals;
+using DotNetNuke.Services.Cryptography;
+using DotNetNuke.Tests.Utilities.Fakes;
+using DotNetNuke.Tests.Utilities.Mocks;
+using Microsoft.Extensions.DependencyInjection;
+using Moq;
+using NUnit.Framework;
+
+[TestFixture]
+public class UrlUtilsTests
+{
+ private static readonly Dictionary HostSettings = new Dictionary();
+
+ [OneTimeSetUp]
+ public static void OneTimeSetUp()
+ {
+ ComponentFactory.RegisterComponent();
+ MockComponentProvider.CreateDataCacheProvider();
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(Mock.Of());
+ serviceCollection.AddSingleton(Mock.Of());
+ serviceCollection.AddSingleton(new FakeHostController(HostSettings));
+ Globals.DependencyProvider = serviceCollection.BuildServiceProvider();
+ }
+
+ [Test]
+ public void CombineEmptyBase()
+ {
+ var result = UrlUtils.Combine(string.Empty, "a/b/c");
+ Assert.AreEqual("a/b/c", result);
+ }
+
+ [Test]
+ public void CombineEmptyRelative()
+ {
+ var result = UrlUtils.Combine("/a/b/c", string.Empty);
+ Assert.AreEqual("/a/b/c", result);
+ }
+
+ [Test]
+ public void CombineRelativeWithBaseTrimsSlashes()
+ {
+ var result = UrlUtils.Combine("/a/b/c/", "/d/e/f/");
+ Assert.AreEqual("/a/b/c/d/e/f/", result);
+ }
+
+ [Test]
+ public void DecodeParameterHandlesRoundTrip()
+ {
+ const string input = "DNN Platform!";
+ var encodedValue = UrlUtils.EncodeParameter(input);
+ var result = UrlUtils.DecodeParameter(encodedValue);
+ Assert.AreEqual(input, result);
+ }
+
+ [Test]
+ public void DecodeParameterHandlesSpecialCharacters()
+ {
+ var result = UrlUtils.DecodeParameter("RE5_O1-$");
+ Assert.AreEqual("DN;_", result);
+ }
+
+ [Test]
+ public void DecryptParameterHandlesRoundTrip()
+ {
+ const string input = "DNN Platform!";
+ var key = Guid.NewGuid().ToString();
+ var encodedValue = UrlUtils.EncryptParameter(input, key);
+ var result = UrlUtils.DecryptParameter(encodedValue, key);
+ Assert.AreEqual(input, result);
+ }
+
+ [Test]
+ public void EncodeParameterReplacesPaddingSymbols()
+ {
+ var result = UrlUtils.EncodeParameter("D");
+ Assert.AreEqual("RA$$", result);
+ }
+
+ [Test]
+ public void EncryptParameterReplacesPaddingSymbols()
+ {
+ var result = UrlUtils.EncryptParameter("D", "key");
+ Assert.IsTrue(result.EndsWith("%3d"));
+ }
+
+ [Test]
+ public void GetParameterNameReturnsName()
+ {
+ var result = UrlUtils.GetParameterName("key=value");
+ Assert.AreEqual("key", result);
+ }
+
+ [Test]
+ public void GetParameterNameReturnsEntireStringIfNoEqualsSign()
+ {
+ var result = UrlUtils.GetParameterName("just-a-key");
+ Assert.AreEqual("just-a-key", result);
+ }
+
+ [Test]
+ public void GetParameterNameReturnsEmptyIfStartsWithEqualsSign()
+ {
+ var result = UrlUtils.GetParameterName("=just-a-value");
+ Assert.AreEqual(string.Empty, result);
+ }
+
+ [Test]
+ public void GetParameterValueReturnsName()
+ {
+ var result = UrlUtils.GetParameterValue("key=value");
+ Assert.AreEqual("value", result);
+ }
+
+ [Test]
+ public void GetParameterValueReturnsEmptyStringIfNoEqualsSign()
+ {
+ var result = UrlUtils.GetParameterValue("just-a-key");
+ Assert.AreEqual(string.Empty, result);
+ }
+
+ [Test]
+ public void GetParameterValueReturnsEntireStringIfStartsWithEqualsSign()
+ {
+ var result = UrlUtils.GetParameterValue("=just-a-value");
+ Assert.AreEqual("just-a-value", result);
+ }
+
+ [Test]
+ public void ClosePopUpGeneratesAJavaScriptUrlWithValues()
+ {
+ var result = UrlUtils.ClosePopUp(false, "/hello", false);
+ Assert.AreEqual("""javascript:dnnModal.closePopUp(false, "/hello")""", result);
+
+ result = UrlUtils.ClosePopUp(true, "blah", false);
+ Assert.AreEqual("""javascript:dnnModal.closePopUp(true, "blah")""", result);
+ }
+
+ [Test]
+ public void ClosePopUpGeneratesAScriptWhenOnClickEventIsTrue()
+ {
+ var result = UrlUtils.ClosePopUp(false, "/somewhere", true);
+ Assert.AreEqual("""dnnModal.closePopUp(false, "/somewhere")""", result);
+ }
+
+ [Test]
+ public void ClosePopUpEncodesUrlParameter()
+ {
+ var result = UrlUtils.ClosePopUp(false, "/somewhere?value=%20hi&two='hey'", true);
+ Assert.AreEqual("""dnnModal.closePopUp(false, "/somewhere?value=%20hi\u0026two=\u0027hey\u0027")""", result);
+ }
+
+ [Test]
+ public void ReplaceQSParamReplacesUnfriendlyParam()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "false", };
+
+ var result = UrlUtils.ReplaceQSParam("/somewhere?value=hi&two=hey", "two", "what");
+ Assert.AreEqual("/somewhere?value=hi&two=what", result);
+ }
+
+ [Test]
+ public void ReplaceQSParamReplacesFriendlyParam()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "true", };
+
+ var result = UrlUtils.ReplaceQSParam("/somewhere/value/hi/two/hey/", "two", "what");
+ Assert.AreEqual("/somewhere/value/hi/two/what/", result);
+ }
+
+ [Test]
+ public void ReplaceQSParamHandlesSpecialCharacters()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "false", };
+
+ var result = UrlUtils.ReplaceQSParam("/somewhere?one.two=three$four&one_two=123", "one.two", "four$3");
+ Assert.AreEqual("/somewhere?one.two=four$3&one_two=123", result);
+ }
+
+ [Test]
+ public void StripQSParamRemovesUnfriendlyParam()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "false", };
+
+ var result = UrlUtils.StripQSParam("/somewhere?value=hi&two=hey&three=x", "two");
+ Assert.AreEqual("/somewhere?value=hi&three=x", result);
+ }
+
+ [Test]
+ public void StripQSParamRemovesFriendlyParam()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "true", };
+
+ var result = UrlUtils.StripQSParam("/somewhere/value/hi/two/hey/", "two");
+ Assert.AreEqual("/somewhere/value/hi/", result);
+ }
+
+ [Test]
+ public void StripQSParamHandlesSpecialCharacters()
+ {
+ HostSettings["UseFriendlyUrls"] = new ConfigurationSetting { Key = "UseFriendlyUrls", Value = "false", };
+
+ var result = UrlUtils.StripQSParam("/somewhere?one.two=three$four&one_two=123", "one.two");
+ Assert.AreEqual("/somewhere?one_two=123", result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlReturnsNullWhenInputIsNull()
+ {
+ var result = UrlUtils.ValidReturnUrl(null);
+ Assert.IsNull(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlReturnsEmptyWhenInputIsEmpty()
+ {
+ var result = UrlUtils.ValidReturnUrl(string.Empty);
+ Assert.IsEmpty(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlDoesNotAcceptDataUrl()
+ {
+ var result = UrlUtils.ValidReturnUrl("data:text/plain,I am text file");
+ Assert.IsEmpty(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlDoesNotAcceptXssAttack()
+ {
+ var result = UrlUtils.ValidReturnUrl("/return?onclick=alert()");
+ Assert.IsEmpty(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlDoesNotAcceptAbsoluteUrlWithoutMatchingDomain()
+ {
+ ComponentFactory.RegisterComponentInstance("PortalSettingsController", Mock.Of());
+
+ var portalAlias = new PortalAliasInfo { HTTPAlias = "dnncommunity.org", };
+ var portalSettings = new PortalSettings(-1, portal: null) { PortalAlias = portalAlias, };
+ var portalControllerMock = new Mock();
+ portalControllerMock.Setup(c => c.GetCurrentPortalSettings()).Returns(portalSettings);
+ PortalController.SetTestableInstance(portalControllerMock.Object);
+
+ var result = UrlUtils.ValidReturnUrl("https://another.evil/return");
+ Assert.IsEmpty(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlDoesAcceptAbsoluteUrlWithMatchingDomain()
+ {
+ ComponentFactory.RegisterComponentInstance("PortalSettingsController", Mock.Of());
+
+ var portalAlias = new PortalAliasInfo { HTTPAlias = "dnncommunity.org", };
+ var portalSettings = new PortalSettings(-1, portal: null) { PortalAlias = portalAlias, };
+ var portalControllerMock = new Mock();
+ portalControllerMock.Setup(c => c.GetCurrentPortalSettings()).Returns(portalSettings);
+ PortalController.SetTestableInstance(portalControllerMock.Object);
+
+ var result = UrlUtils.ValidReturnUrl("https://dnncommunity.org/return");
+ Assert.AreEqual("https://dnncommunity.org/return", result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlDoesNotAcceptAbsoluteUrlWithoutProtocolWhenDomainDoesNotMatch()
+ {
+ ComponentFactory.RegisterComponentInstance("PortalSettingsController", Mock.Of());
+
+ var portalAlias = new PortalAliasInfo { HTTPAlias = "dnncommunity.org", };
+ var portalSettings = new PortalSettings(-1, portal: null) { PortalAlias = portalAlias, };
+ var portalControllerMock = new Mock();
+ portalControllerMock.Setup(c => c.GetCurrentPortalSettings()).Returns(portalSettings);
+ PortalController.SetTestableInstance(portalControllerMock.Object);
+
+ var result = UrlUtils.ValidReturnUrl("/////dnncommunity.net/return");
+ Assert.IsEmpty(result);
+ }
+
+ [Test]
+ public void ValidateReturnUrlAcceptsAbsoluteUrlWithoutProtocolWhenDomainDoesMatches()
+ {
+ ComponentFactory.RegisterComponentInstance("PortalSettingsController", Mock.Of());
+
+ var portalAlias = new PortalAliasInfo { HTTPAlias = "dnncommunity.org", };
+ var portalSettings = new PortalSettings(-1, portal: null) { PortalAlias = portalAlias, };
+ var portalControllerMock = new Mock();
+ portalControllerMock.Setup(c => c.GetCurrentPortalSettings()).Returns(portalSettings);
+ PortalController.SetTestableInstance(portalControllerMock.Object);
+
+ var result = UrlUtils.ValidReturnUrl("/////dnncommunity.org/return");
+ Assert.AreEqual("//dnncommunity.org/return", result);
+ }
+
+ [Test]
+ public void IsPopUpIsTrueWhenPopUpParameterIsOnUrl()
+ {
+ var result = UrlUtils.IsPopUp("/page?popUp=true");
+ Assert.IsTrue(result);
+ }
+
+ [Test]
+ public void IsPopUpIsFalseWhenPopUpParameterIsNotOnUrl()
+ {
+ var result = UrlUtils.IsPopUp("/page");
+ Assert.IsFalse(result);
+ }
+}
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj b/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj
index c7b005ec7f3..eef43699581 100644
--- a/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj
@@ -146,6 +146,7 @@
+
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/Providers/Folder/FileManagerTests.cs b/DNN Platform/Tests/DotNetNuke.Tests.Core/Providers/Folder/FileManagerTests.cs
index 0ddd620c0a4..2c4ba952303 100644
--- a/DNN Platform/Tests/DotNetNuke.Tests.Core/Providers/Folder/FileManagerTests.cs
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/Providers/Folder/FileManagerTests.cs
@@ -200,6 +200,8 @@ public void AddFile_Checks_Space_For_Stream_Length()
var fileContent = new MemoryStream(Encoding.ASCII.GetBytes("some data here"));
+ this.hostController.Setup(c => c.GetString("FileExtensions")).Returns("");
+
this.portalController.Setup(pc => pc.HasSpaceAvailable(It.IsAny(), It.IsAny())).Returns(true);
this.globals.Setup(g => g.GetSubFolderPath(Constants.FOLDER_ValidFilePath, Constants.CONTENT_ValidPortalId)).Returns(Constants.FOLDER_ValidFolderRelativePath);
@@ -267,6 +269,7 @@ public void AddFile_No_Error_When_File_Content_Is_Valid()
this.portalController.Setup(pc => pc.HasSpaceAvailable(Constants.CONTENT_ValidPortalId, fileContent.Length)).Returns(true);
this.mockFileManager.Setup(mfm => mfm.IsAllowedExtension(Constants.FOLDER_ValidSvgFileName)).Returns(true);
this.mockFileManager.Setup(mfm => mfm.IsImageFile(It.IsAny())).Returns(false);
+ this.hostController.Setup(c => c.GetString("FileExtensions")).Returns("");
this.mockFileManager.Object.AddFile(this.folderInfo.Object, Constants.FOLDER_ValidSvgFileName, fileContent, false, false, Constants.CONTENTTYPE_ValidContentType);
}
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Utilities/DotNetNuke.Tests.Utilities.csproj b/DNN Platform/Tests/DotNetNuke.Tests.Utilities/DotNetNuke.Tests.Utilities.csproj
index 41c136137c8..f7d78d5db80 100644
--- a/DNN Platform/Tests/DotNetNuke.Tests.Utilities/DotNetNuke.Tests.Utilities.csproj
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Utilities/DotNetNuke.Tests.Utilities.csproj
@@ -119,6 +119,7 @@
+
diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Utilities/Fakes/FakeHostController.cs b/DNN Platform/Tests/DotNetNuke.Tests.Utilities/Fakes/FakeHostController.cs
new file mode 100644
index 00000000000..8389a8ed723
--- /dev/null
+++ b/DNN Platform/Tests/DotNetNuke.Tests.Utilities/Fakes/FakeHostController.cs
@@ -0,0 +1,195 @@
+// 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
+
+namespace DotNetNuke.Tests.Utilities.Fakes;
+
+using System;
+using System.Collections.Generic;
+using DotNetNuke.Abstractions.Application;
+using DotNetNuke.Abstractions.Settings;
+using DotNetNuke.Common.Utilities;
+using DotNetNuke.Entities;
+using DotNetNuke.Entities.Controllers;
+
+public class FakeHostController : IHostController, IHostSettingsService
+{
+ private readonly IReadOnlyDictionary settings;
+
+ public FakeHostController(IReadOnlyDictionary settings)
+ {
+ this.settings = settings;
+ }
+
+ public bool GetBoolean(string key) => this.GetBoolean(key, Null.NullBoolean);
+
+ public bool GetBoolean(string key, bool defaultValue)
+ {
+ if (this.settings.TryGetValue(key, out var setting))
+ {
+ return setting.Value.StartsWith("Y", StringComparison.InvariantCultureIgnoreCase) || setting.Value.Equals("TRUE", StringComparison.InvariantCultureIgnoreCase);
+ }
+
+ return defaultValue;
+ }
+
+ double IHostSettingsService.GetDouble(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ double IHostSettingsService.GetDouble(string key, double defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ string IHostSettingsService.GetEncryptedString(string key, string passPhrase)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ int IHostSettingsService.GetInteger(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ int IHostSettingsService.GetInteger(string key, int defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ IDictionary IHostSettingsService.GetSettings()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ IDictionary IHostSettingsService.GetSettingsDictionary()
+ {
+ return this.GetSettingsDictionary();
+ }
+
+ string IHostSettingsService.GetString(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ string IHostSettingsService.GetString(string key, string defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostSettingsService.IncrementCrmVersion(bool includeOverridingPortals)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(IConfigurationSetting config)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(IConfigurationSetting config, bool clearCache)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(IDictionary settings)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostSettingsService.Update(string key, string value)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostSettingsService.Update(string key, string value, bool clearCache)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostSettingsService.UpdateEncryptedString(string key, string value, string passPhrase)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ double IHostController.GetDouble(string key, double defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ double IHostController.GetDouble(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ int IHostController.GetInteger(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ int IHostController.GetInteger(string key, int defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ Dictionary IHostController.GetSettings()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public Dictionary GetSettingsDictionary()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ string IHostController.GetEncryptedString(string key, string passPhrase)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ string IHostController.GetString(string key)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ string IHostController.GetString(string key, string defaultValue)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(Dictionary settings)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(ConfigurationSetting config)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void Update(ConfigurationSetting config, bool clearCache)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostController.Update(string key, string value, bool clearCache)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostController.Update(string key, string value)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostController.UpdateEncryptedString(string key, string value, string passPhrase)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ void IHostController.IncrementCrmVersion(bool includeOverridingPortals)
+ {
+ throw new System.NotImplementedException();
+ }
+}
diff --git a/DNN_Platform.sln.DotSettings b/DNN_Platform.sln.DotSettings
index df1eaae620f..5bf3af7b796 100644
--- a/DNN_Platform.sln.DotSettings
+++ b/DNN_Platform.sln.DotSettings
@@ -153,6 +153,7 @@
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
+ True
True
True
True