diff --git a/src/Umbraco.Abstractions/IO/IIOHelper.cs b/src/Umbraco.Abstractions/IO/IIOHelper.cs
index 8b090f7f50..2d535a8d1e 100644
--- a/src/Umbraco.Abstractions/IO/IIOHelper.cs
+++ b/src/Umbraco.Abstractions/IO/IIOHelper.cs
@@ -59,13 +59,6 @@ namespace Umbraco.Core.IO
///
void SetRootDirectory(string rootPath);
- ///
- /// Check to see if filename passed has any special chars in it and strips them to create a safe filename. Used to overcome an issue when Umbraco is used in IE in an intranet environment.
- ///
- /// The filename passed to the file handler from the upload field.
- /// A safe filename without any path specific chars.
- string SafeFileName(string filePath);
-
void EnsurePathExists(string path);
///
diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Abstractions/IO/IOHelper.cs
similarity index 95%
rename from src/Umbraco.Core/IO/IOHelper.cs
rename to src/Umbraco.Abstractions/IO/IOHelper.cs
index 1b0fed9c0f..672228e3ca 100644
--- a/src/Umbraco.Core/IO/IOHelper.cs
+++ b/src/Umbraco.Abstractions/IO/IOHelper.cs
@@ -255,17 +255,6 @@ namespace Umbraco.Core.IO
_rootDir = rootPath;
}
- ///
- /// Check to see if filename passed has any special chars in it and strips them to create a safe filename. Used to overcome an issue when Umbraco is used in IE in an intranet environment.
- ///
- /// The filename passed to the file handler from the upload field.
- /// A safe filename without any path specific chars.
- public string SafeFileName(string filePath)
- {
- // use string extensions
- return filePath.ToSafeFileName();
- }
-
public void EnsurePathExists(string path)
{
var absolutePath = MapPath(path);
diff --git a/src/Umbraco.Abstractions/IO/MediaFileSystem.cs b/src/Umbraco.Abstractions/IO/MediaFileSystem.cs
index 02564820c5..cd978cc392 100644
--- a/src/Umbraco.Abstractions/IO/MediaFileSystem.cs
+++ b/src/Umbraco.Abstractions/IO/MediaFileSystem.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
+using Umbraco.Core.Strings;
namespace Umbraco.Core.IO
{
@@ -15,20 +16,18 @@ namespace Umbraco.Core.IO
public class MediaFileSystem : FileSystemWrapper, IMediaFileSystem
{
private readonly IMediaPathScheme _mediaPathScheme;
- private readonly IContentSection _contentConfig;
private readonly ILogger _logger;
- private readonly IIOHelper _ioHelper;
+ private readonly IShortStringHelper _shortStringHelper;
///
/// Initializes a new instance of the class.
///
- public MediaFileSystem(IFileSystem innerFileSystem, IContentSection contentConfig, IMediaPathScheme mediaPathScheme, ILogger logger, IIOHelper ioHelper)
+ public MediaFileSystem(IFileSystem innerFileSystem, IMediaPathScheme mediaPathScheme, ILogger logger, IShortStringHelper shortStringHelper)
: base(innerFileSystem)
{
- _contentConfig = contentConfig;
_mediaPathScheme = mediaPathScheme;
_logger = logger;
- _ioHelper = ioHelper;
+ _shortStringHelper = shortStringHelper;
}
///
@@ -65,7 +64,7 @@ namespace Umbraco.Core.IO
{
filename = Path.GetFileName(filename);
if (filename == null) throw new ArgumentException("Cannot become a safe filename.", nameof(filename));
- filename = _ioHelper.SafeFileName(filename.ToLowerInvariant());
+ filename = _shortStringHelper.CleanStringForSafeFileName(filename.ToLowerInvariant());
return _mediaPathScheme.GetFilePath(this, cuid, puid, filename);
}
@@ -75,7 +74,7 @@ namespace Umbraco.Core.IO
{
filename = Path.GetFileName(filename);
if (filename == null) throw new ArgumentException("Cannot become a safe filename.", nameof(filename));
- filename = _ioHelper.SafeFileName(filename.ToLowerInvariant());
+ filename = _shortStringHelper.CleanStringForSafeFileName(filename.ToLowerInvariant());
return _mediaPathScheme.GetFilePath(this, cuid, puid, filename, prevpath);
}
diff --git a/src/Umbraco.Abstractions/StringExtensions.cs b/src/Umbraco.Abstractions/StringExtensions.cs
index e9a69f40a5..37a6ae4258 100644
--- a/src/Umbraco.Abstractions/StringExtensions.cs
+++ b/src/Umbraco.Abstractions/StringExtensions.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
+using Umbraco.Core.IO;
namespace Umbraco.Core
{
@@ -1213,5 +1214,80 @@ namespace Umbraco.Core
///
public static string NullOrWhiteSpaceAsNull(this string text)
=> string.IsNullOrWhiteSpace(text) ? null : text;
+
+ ///
+ /// Ensures that a path has `~/` as prefix
+ ///
+ ///
+ ///
+ public static string EnsurePathIsApplicationRootPrefixed(this string path)
+ {
+ if (path.StartsWith("~/"))
+ return path;
+ if (path.StartsWith("/") == false && path.StartsWith("\\") == false)
+ path = string.Format("/{0}", path);
+ if (path.StartsWith("~") == false)
+ path = string.Format("~{0}", path);
+ return path;
+ }
+
+ ///
+ /// Checks if a given path is a full path including drive letter
+ ///
+ ///
+ ///
+ // From: http://stackoverflow.com/a/35046453/5018
+ public static bool IsFullPath(this string path)
+ {
+ return string.IsNullOrWhiteSpace(path) == false
+ && path.IndexOfAny(Path.GetInvalidPathChars().ToArray()) == -1
+ && Path.IsPathRooted(path)
+ && Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) == false;
+ }
+
+ ///
+ /// Based on the input string, this will detect if the string is a JS path or a JS snippet.
+ /// If a path cannot be determined, then it is assumed to be a snippet the original text is returned
+ /// with an invalid attempt, otherwise a valid attempt is returned with the resolved path
+ ///
+ ///
+ ///
+ ///
+ /// This is only used for legacy purposes for the Action.JsSource stuff and shouldn't be needed in v8
+ ///
+ internal static Attempt DetectIsJavaScriptPath(this string input, IIOHelper ioHelper)
+ {
+ //validate that this is a url, if it is not, we'll assume that it is a text block and render it as a text
+ //block instead.
+ var isValid = true;
+
+ if (Uri.IsWellFormedUriString(input, UriKind.RelativeOrAbsolute))
+ {
+ //ok it validates, but so does alert('hello'); ! so we need to do more checks
+
+ //here are the valid chars in a url without escaping
+ if (Regex.IsMatch(input, @"[^a-zA-Z0-9-._~:/?#\[\]@!$&'\(\)*\+,%;=]"))
+ isValid = false;
+
+ //we'll have to be smarter and just check for certain js patterns now too!
+ var jsPatterns = new[] { @"\+\s*\=", @"\);", @"function\s*\(", @"!=", @"==" };
+ if (jsPatterns.Any(p => Regex.IsMatch(input, p)))
+ isValid = false;
+
+ if (isValid)
+ {
+ var resolvedUrlResult = ioHelper.TryResolveUrl(input);
+ //if the resolution was success, return it, otherwise just return the path, we've detected
+ // it's a path but maybe it's relative and resolution has failed, etc... in which case we're just
+ // returning what was given to us.
+ return resolvedUrlResult.Success
+ ? resolvedUrlResult
+ : Attempt.Succeed(input);
+ }
+ }
+
+ return Attempt.Fail(input);
+ }
+
}
}
diff --git a/src/Umbraco.Configuration/ConfigsFactory.cs b/src/Umbraco.Configuration/ConfigsFactory.cs
index e7ee72656f..6619da90a4 100644
--- a/src/Umbraco.Configuration/ConfigsFactory.cs
+++ b/src/Umbraco.Configuration/ConfigsFactory.cs
@@ -13,6 +13,7 @@ namespace Umbraco.Core.Configuration
}
public IHostingSettings HostingSettings { get; } = new HostingSettings();
+ public IUmbracoSettingsSection UmbracoSettings { get; }
public Configs Create(IIOHelper ioHelper)
{
diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs
index 2a61c44323..db553c3b4a 100644
--- a/src/Umbraco.Core/ContentExtensions.cs
+++ b/src/Umbraco.Core/ContentExtensions.cs
@@ -11,6 +11,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
namespace Umbraco.Core
{
@@ -136,9 +137,9 @@ namespace Umbraco.Core
if (filename == null || filestream == null) return;
// get a safe & clean filename
- var ioHelper = Current.Factory.GetInstance();
+ var shortStringHelper = Current.Factory.GetInstance();
- filename = ioHelper.SafeFileName(filename);
+ filename = shortStringHelper.CleanStringForSafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower();
diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs
index b7baa8cd60..f9f9199dad 100644
--- a/src/Umbraco.Core/StringExtensions.cs
+++ b/src/Umbraco.Core/StringExtensions.cs
@@ -14,51 +14,6 @@ namespace Umbraco.Core
///
public static class StringExtensions
{
- ///
- /// Based on the input string, this will detect if the string is a JS path or a JS snippet.
- /// If a path cannot be determined, then it is assumed to be a snippet the original text is returned
- /// with an invalid attempt, otherwise a valid attempt is returned with the resolved path
- ///
- ///
- ///
- ///
- /// This is only used for legacy purposes for the Action.JsSource stuff and shouldn't be needed in v8
- ///
- internal static Attempt DetectIsJavaScriptPath(this string input)
- {
- //validate that this is a url, if it is not, we'll assume that it is a text block and render it as a text
- //block instead.
- var isValid = true;
-
- if (Uri.IsWellFormedUriString(input, UriKind.RelativeOrAbsolute))
- {
- //ok it validates, but so does alert('hello'); ! so we need to do more checks
-
- //here are the valid chars in a url without escaping
- if (Regex.IsMatch(input, @"[^a-zA-Z0-9-._~:/?#\[\]@!$&'\(\)*\+,%;=]"))
- isValid = false;
-
- //we'll have to be smarter and just check for certain js patterns now too!
- var jsPatterns = new[] { @"\+\s*\=", @"\);", @"function\s*\(", @"!=", @"==" };
- if (jsPatterns.Any(p => Regex.IsMatch(input, p)))
- isValid = false;
-
- if (isValid)
- {
- var ioHelper = Current.Factory.GetInstance();
-
- var resolvedUrlResult = ioHelper.TryResolveUrl(input);
- //if the resolution was success, return it, otherwise just return the path, we've detected
- // it's a path but maybe it's relative and resolution has failed, etc... in which case we're just
- // returning what was given to us.
- return resolvedUrlResult.Success
- ? resolvedUrlResult
- : Attempt.Succeed(input);
- }
- }
-
- return Attempt.Fail(input);
- }
// FORMAT STRINGS
@@ -227,34 +182,8 @@ namespace Umbraco.Core
return Current.ShortStringHelper.CleanStringForSafeFileName(text, culture);
}
- ///
- /// Checks if a given path is a full path including drive letter
- ///
- ///
- ///
- // From: http://stackoverflow.com/a/35046453/5018
- internal static bool IsFullPath(this string path)
- {
- return string.IsNullOrWhiteSpace(path) == false
- && path.IndexOfAny(Path.GetInvalidPathChars().ToArray()) == -1
- && Path.IsPathRooted(path)
- && Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) == false;
- }
- ///
- /// Ensures that a path has `~/` as prefix
- ///
- ///
- ///
- internal static string EnsurePathIsApplicationRootPrefixed(this string path)
- {
- if (path.StartsWith("~/"))
- return path;
- if (path.StartsWith("/") == false && path.StartsWith("\\") == false)
- path = string.Format("/{0}", path);
- if (path.StartsWith("~") == false)
- path = string.Format("~{0}", path);
- return path;
- }
+
+
}
}
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 4d3bf9ebc0..80690c7dd5 100755
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -159,7 +159,6 @@
-
diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs
index 76d1ce85fc..9358923f72 100644
--- a/src/Umbraco.Tests/IO/FileSystemsTests.cs
+++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs
@@ -14,6 +14,7 @@ using Umbraco.Core.Services;
using Umbraco.Tests.Components;
using Umbraco.Tests.TestHelpers;
using Umbraco.Core.Composing.CompositionExtensions;
+using Umbraco.Core.Strings;
using FileSystems = Umbraco.Core.IO.FileSystems;
namespace Umbraco.Tests.IO
@@ -34,6 +35,7 @@ namespace Umbraco.Tests.IO
composition.Register(_ => Mock.Of());
composition.Register(_ => Mock.Of());
composition.Register(_ => Mock.Of());
+ composition.Register(_ => TestHelper.ShortStringHelper);
composition.Register(_ => TestHelper.IOHelper);
composition.RegisterUnique();
composition.RegisterUnique(TestHelper.IOHelper);
diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs
index d8557230b6..a68272c0ce 100644
--- a/src/Umbraco.Tests/Models/MediaXmlTest.cs
+++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs
@@ -31,13 +31,13 @@ namespace Umbraco.Tests.Models
// reference, so static ctor runs, so event handlers register
// and then, this will reset the width, height... because the file does not exist, of course ;-(
var logger = Mock.Of();
- var ioHelper = Mock.Of();
+ var shortStringHelper = Mock.Of();
var scheme = Mock.Of();
var config = Mock.Of();
var dataTypeService = Mock.Of();
var localizationService = Mock.Of();
- var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger, ioHelper);
+ var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, shortStringHelper);
var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config, dataTypeService, localizationService);
var media = MockedMedia.CreateMediaImage(mediaType, -1);
diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs
index 58345e2064..5e18e8ce78 100644
--- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs
+++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs
@@ -16,6 +16,7 @@ using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
using Umbraco.Tests.Components;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Models;
@@ -78,10 +79,9 @@ namespace Umbraco.Tests.PropertyEditors
var logger = Mock.Of();
var scheme = Mock.Of();
- var config = Mock.Of();
- var ioHelper = Mock.Of();
+ var shortStringHelper = Mock.Of();
- var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger, ioHelper);
+ var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, shortStringHelper);
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of(), Mock.Of(), Mock.Of(), TestHelper.IOHelper)) { Id = 1 });
diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs
index 66d0a973a7..286f2fd9e4 100644
--- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs
+++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Strings
[TestCase("/Test.js function(){return true;}", false)]
public void Detect_Is_JavaScript_Path(string input, bool result)
{
- var output = input.DetectIsJavaScriptPath();
+ var output = input.DetectIsJavaScriptPath(IOHelper);
Assert.AreEqual(result, output.Success);
}
diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
index ca52c0b222..fc14c04da8 100644
--- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
@@ -20,6 +20,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Net;
using Umbraco.Web;
@@ -82,6 +83,8 @@ namespace Umbraco.Tests.TestHelpers
}
}
+ public static IShortStringHelper ShortStringHelper => new DefaultShortStringHelper(new DefaultShortStringHelperConfig());
+
public static IIOHelper IOHelper = new IOHelper(GetHostingEnvironment());
///
diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs
index d79ea3500e..50288f9ac3 100644
--- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs
@@ -108,9 +108,10 @@ namespace Umbraco.Tests.TestHelpers
if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory));
var scheme = Mock.Of();
- var config = Mock.Of();
- var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger, ioHelper);
+ var shortStringHelper = Mock.Of();
+
+ var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, shortStringHelper);
var externalLoginService = GetLazyService(factory, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c)));
var publicAccessService = GetLazyService(factory, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c)));
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index c84089475e..eaf20bb810 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -104,6 +104,7 @@ namespace Umbraco.Tests.Testing
protected ILogger Logger => Factory.GetInstance();
protected IIOHelper IOHelper { get; private set; }
+ protected IShortStringHelper ShortStringHelper { get; private set; }
protected IUmbracoVersion UmbracoVersion { get; private set; }
protected ITypeFinder TypeFinder { get; private set; }
@@ -143,6 +144,7 @@ namespace Umbraco.Tests.Testing
var (logger, profiler) = GetLoggers(Options.Logger);
var proflogger = new ProfilingLogger(logger, profiler);
IOHelper = TestHelper.IOHelper;
+ ShortStringHelper = TestHelper.ShortStringHelper;
TypeFinder = new TypeFinder(logger);
var appCaches = GetAppCaches();
@@ -160,6 +162,7 @@ namespace Umbraco.Tests.Testing
Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache);
+ Composition.RegisterUnique(ShortStringHelper);
Composition.RegisterUnique(IOHelper);
Composition.RegisterUnique(UmbracoVersion);
Composition.RegisterUnique(TypeFinder);
@@ -364,10 +367,8 @@ namespace Umbraco.Tests.Testing
var logger = Mock.Of();
var scheme = Mock.Of();
- var config = Mock.Of();
- var ioHelper = Mock.Of();
- var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger, ioHelper);
+ var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, ShortStringHelper);
Composition.RegisterUnique(factory => mediaFileSystem);
// no factory (noop)
diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs
index d65006e6bb..313df4b619 100644
--- a/src/Umbraco.Web/UmbracoApplicationBase.cs
+++ b/src/Umbraco.Web/UmbracoApplicationBase.cs
@@ -10,6 +10,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
+using Umbraco.Core.Strings;
using Umbraco.Web.Hosting;
namespace Umbraco.Web