From de0a578dc8439b95e432a90279f48869c87c2be8 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 16 Mar 2020 14:48:41 +0100 Subject: [PATCH] Fix for ModelsBuilderConfig --- .../ModelsBuilderConfig.cs | 33 +------------ .../ModelsBuilderConfigExtensions.cs | 49 ++++++++++++++++++- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../ModelsBuilder/ConfigTests.cs | 6 +-- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/Umbraco.Configuration/ModelsBuilderConfig.cs b/src/Umbraco.Configuration/ModelsBuilderConfig.cs index a855d17d96..79f4b065a0 100644 --- a/src/Umbraco.Configuration/ModelsBuilderConfig.cs +++ b/src/Umbraco.Configuration/ModelsBuilderConfig.cs @@ -57,10 +57,8 @@ namespace Umbraco.Configuration value = ConfigurationManager.AppSettings[Prefix + "ModelsDirectory"]; if (!string.IsNullOrWhiteSpace(value)) { - var root = "~/"; - // GetModelsDirectory will ensure that the path is safe - ModelsDirectory = GetModelsDirectory(root, value, AcceptUnsafeModelsDirectory); + ModelsDirectory = value; } // default: 0 @@ -98,36 +96,7 @@ namespace Umbraco.Configuration DebugLevel = debugLevel; } - // internal for tests - internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe) - { - // making sure it is safe, ie under the website root, - // unless AcceptUnsafeModelsDirectory and then everything is OK. - if (!Path.IsPathRooted(root)) - throw new ConfigurationErrorsException($"Root is not rooted \"{root}\"."); - - if (config.StartsWith("~/")) - { - var dir = Path.Combine(root, config.TrimStart("~/")); - - // sanitize - GetFullPath will take care of any relative - // segments in path, eg '../../foo.tmp' - it may throw a SecurityException - // if the combined path reaches illegal parts of the filesystem - dir = Path.GetFullPath(dir); - root = Path.GetFullPath(root); - - if (!dir.StartsWith(root) && !acceptUnsafe) - throw new ConfigurationErrorsException($"Invalid models directory \"{config}\"."); - - return dir; - } - - if (acceptUnsafe) - return Path.GetFullPath(config); - - throw new ConfigurationErrorsException($"Invalid models directory \"{config}\"."); - } /// /// Gets a value indicating whether the whole models experience is enabled. diff --git a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs index f4b13f52f3..3e3b116395 100644 --- a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs +++ b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs @@ -1,12 +1,57 @@ -using Umbraco.Core.IO; +using System.Configuration; +using System.IO; +using Umbraco.Core.IO; namespace Umbraco.Core.Configuration { public static class ModelsBuilderConfigExtensions { + private static string _modelsDirectoryAbsolute = null; + public static string ModelsDirectoryAbsolute(this IModelsBuilderConfig modelsBuilderConfig, IIOHelper ioHelper) { - return ioHelper.MapPath(modelsBuilderConfig.ModelsDirectory); + + if (_modelsDirectoryAbsolute is null) + { + var modelsDirectory = modelsBuilderConfig.ModelsDirectory; + var root = ioHelper.MapPath("~/"); + + _modelsDirectoryAbsolute = GetModelsDirectory(root, modelsDirectory, + modelsBuilderConfig.AcceptUnsafeModelsDirectory); + } + + return _modelsDirectoryAbsolute; + } + + // internal for tests + internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe) + { + // making sure it is safe, ie under the website root, + // unless AcceptUnsafeModelsDirectory and then everything is OK. + + if (!Path.IsPathRooted(root)) + throw new ConfigurationErrorsException($"Root is not rooted \"{root}\"."); + + if (config.StartsWith("~/")) + { + var dir = Path.Combine(root, config.TrimStart("~/")); + + // sanitize - GetFullPath will take care of any relative + // segments in path, eg '../../foo.tmp' - it may throw a SecurityException + // if the combined path reaches illegal parts of the filesystem + dir = Path.GetFullPath(dir); + root = Path.GetFullPath(root); + + if (!dir.StartsWith(root) && !acceptUnsafe) + throw new ConfigurationErrorsException($"Invalid models directory \"{config}\"."); + + return dir; + } + + if (acceptUnsafe) + return Path.GetFullPath(config); + + throw new ConfigurationErrorsException($"Invalid models directory \"{config}\"."); } } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7a15e7fbed..c083cccf8f 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs b/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs index 260fe37953..d2acc90439 100644 --- a/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs +++ b/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs @@ -2,7 +2,7 @@ using NUnit.Framework; using Umbraco.Configuration; using Umbraco.Core; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Configuration; namespace Umbraco.Tests.ModelsBuilder { @@ -35,7 +35,7 @@ namespace Umbraco.Tests.ModelsBuilder [TestCase("c:/path/to/root", "c:/another/path/to/elsewhere", true, "c:\\another\\path\\to\\elsewhere")] public void GetModelsDirectoryTests(string root, string config, bool acceptUnsafe, string expected) { - Assert.AreEqual(expected, ModelsBuilderConfig.GetModelsDirectory(root, config, acceptUnsafe)); + Assert.AreEqual(expected, ModelsBuilderConfigExtensions.GetModelsDirectory(root, config, acceptUnsafe)); } [TestCase("c:/path/to/root", "~/../../dir/models", false)] @@ -44,7 +44,7 @@ namespace Umbraco.Tests.ModelsBuilder { Assert.Throws(() => { - var modelsDirectory = ModelsBuilderConfig.GetModelsDirectory(root, config, acceptUnsafe); + var modelsDirectory = ModelsBuilderConfigExtensions.GetModelsDirectory(root, config, acceptUnsafe); }); } }