diff --git a/build/Build.proj b/build/Build.proj deleted file mode 100644 index 498637ccd4..0000000000 --- a/build/Build.proj +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - ..\MSBuildCommunityTasks - ..\UmbracoMSBuildTasks - - - - - - - - - - .$(BUILD_NUMBER) - - - - Release - _BuildOutput\ - UmbracoCms$(DECIMAL_BUILD_NUMBER).zip - UmbracoCms.AllBinaries$(DECIMAL_BUILD_NUMBER).zip - UmbracoCms.WebPI$(DECIMAL_BUILD_NUMBER).zip - False - ..\..\build\$(BuildFolder) - $(MSBuildProjectDirectory)\$(BuildFolder) - $(BuildFolder)bin\ - $(BuildFolder)WebApp\ - $(BuildFolder)WebPi\ - $(BuildFolderRelativeToProjects)bin\ - $(BuildFolderAbsolutePath)bin\ - $(BuildFolderRelativeToProjects)WebApp\ - $(BuildFolderAbsolutePath)WebApp\ - $(BuildFolderRelativeToProjects)WebPi\ - $(BuildFolderAbsolutePath)WebPi\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs b/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs new file mode 100644 index 0000000000..c0773e64e3 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + public class FileSystemProviderElement : ConfigurationElement + { + private const string ALIAS_KEY = "alias"; + private const string TYPE_KEY = "type"; + private const string PARAMETERS_KEY = "Parameters"; + + [ConfigurationProperty(ALIAS_KEY, IsKey = true, IsRequired = true)] + public string Alias + { + get + { + return ((string)(base[ALIAS_KEY])); + } + } + + [ConfigurationProperty(TYPE_KEY, IsKey = false, IsRequired = true)] + public string Type + { + get + { + return ((string)(base[TYPE_KEY])); + } + } + + [ConfigurationProperty(PARAMETERS_KEY, IsDefaultCollection = true, IsRequired = false)] + public KeyValueConfigurationCollection Parameters + { + get + { + return ((KeyValueConfigurationCollection)(base[PARAMETERS_KEY])); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs b/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs new file mode 100644 index 0000000000..0604560939 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + [ConfigurationCollection(typeof(FileSystemProviderElement), AddItemName = "Provider")] + public class FileSystemProviderElementCollection : ConfigurationElementCollection + { + protected override ConfigurationElement CreateNewElement() + { + return new FileSystemProviderElement(); + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((FileSystemProviderElement)(element)).Alias; + } + + new public FileSystemProviderElement this[string key] + { + get + { + return (FileSystemProviderElement)BaseGet(key); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs b/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs new file mode 100644 index 0000000000..a893d541a6 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + public class FileSystemProvidersSection : ConfigurationSection + { + private const string PROVIDERS_KEY = "providers"; + + [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)] + public FileSystemProviderElementCollection Providers + { + get { return ((FileSystemProviderElementCollection)(base[""])); } + } + } +} diff --git a/src/Umbraco.Core/IO/AbstractFileSystem.cs b/src/Umbraco.Core/IO/AbstractFileSystem.cs new file mode 100644 index 0000000000..3e49742c03 --- /dev/null +++ b/src/Umbraco.Core/IO/AbstractFileSystem.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.IO +{ + public abstract class AbstractFileSystem : IFileSystem + { + public abstract IEnumerable GetDirectories(string path); + + public abstract void DeleteDirectory(string path); + + public abstract void DeleteDirectory(string path, bool recursive); + + public abstract bool DirectoryExists(string path); + + public abstract void AddFile(string path, Stream stream); + + public abstract void AddFile(string path, Stream stream, bool overrideIfExists); + + public abstract IEnumerable GetFiles(string path); + + public abstract IEnumerable GetFiles(string path, string filter); + + public abstract Stream OpenFile(string path); + + public abstract void DeleteFile(string path); + + public abstract bool FileExists(string path); + + public abstract string GetRelativePath(string fullPathOrUrl); + + public abstract string GetFullPath(string path); + + public abstract string GetUrl(string path); + + public virtual long GetSize(string path) + { + var s = OpenFile(path); + var size = s.Length; + s.Close(); + + return size; + } + + public abstract DateTimeOffset GetLastModified(string path); + + public abstract DateTimeOffset GetCreated(string path); + } +} diff --git a/src/Umbraco.Core/IO/FileSystemProvider.cs b/src/Umbraco.Core/IO/FileSystemProvider.cs new file mode 100644 index 0000000000..31f767f28e --- /dev/null +++ b/src/Umbraco.Core/IO/FileSystemProvider.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.IO +{ + internal class FileSystemProvider + { + public const string Media = "media"; + } +} diff --git a/src/Umbraco.Core/IO/FileSystemProviderManager.cs b/src/Umbraco.Core/IO/FileSystemProviderManager.cs new file mode 100644 index 0000000000..da4a1e8dec --- /dev/null +++ b/src/Umbraco.Core/IO/FileSystemProviderManager.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.IO +{ + internal class FileSystemProviderManager + { + private readonly FileSystemProvidersSection _config; + + #region Singleton + + private static readonly FileSystemProviderManager Instance = new FileSystemProviderManager(); + + public static FileSystemProviderManager Current + { + get { return Instance; } + } + + #endregion + + #region Constructors + + public FileSystemProviderManager() + { + _config = (FileSystemProvidersSection)ConfigurationManager.GetSection("FileSystemProviders"); + } + + #endregion + + public IFileSystem GetFileSystemProvider(string alias) + { + var providerConfig = _config.Providers[alias]; + if(providerConfig == null) + throw new ArgumentException(string.Format("No provider found with the alias '{0}'", alias)); + + var providerType = Type.GetType(providerConfig.Type); + if(providerType == null) + throw new InvalidOperationException(string.Format("Could not find type '{0}'", providerConfig.Type)); + + if (providerType.IsAssignableFrom(typeof(IFileSystem))) + throw new InvalidOperationException(string.Format("The type '{0}' does not implement IFileSystem", providerConfig.Type)); + + var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0; + var constructor = providerType.GetConstructors() + .SingleOrDefault(x => x.GetParameters().Count() == paramCount + && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name))); + if(constructor == null) + throw new InvalidOperationException(string.Format("Could not find constructor for type '{0}' which accepts {1} parameters", providerConfig.Type, paramCount)); + + var parameters = new object[paramCount]; + for(var i = 0; i < paramCount; i++) + parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value; + + return (IFileSystem) constructor.Invoke(parameters); + } + } +} diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs new file mode 100644 index 0000000000..0bb11527ea --- /dev/null +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Umbraco.Core.IO +{ + internal interface IFileSystem + { + IEnumerable GetDirectories(string path); + + void DeleteDirectory(string path); + + void DeleteDirectory(string path, bool recursive); + + bool DirectoryExists(string path); + + + void AddFile(string path, Stream stream); + + void AddFile(string path, Stream stream, bool overrideIfExists); + + IEnumerable GetFiles(string path); + + IEnumerable GetFiles(string path, string filter); + + Stream OpenFile(string path); + + void DeleteFile(string path); + + bool FileExists(string path); + + string GetRelativePath(string fullPathOrUrl); + + string GetFullPath(string path); + + string GetUrl(string path); + + long GetSize(string path); + + DateTimeOffset GetLastModified(string path); + + DateTimeOffset GetCreated(string path); + } +} diff --git a/src/Umbraco.Core/IO/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs new file mode 100644 index 0000000000..5b2cbd7db5 --- /dev/null +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; + +namespace Umbraco.Core.IO +{ + internal class PhysicalFileSystem : AbstractFileSystem + { + private readonly string _rootPath; + private readonly string _rootUrl; + + public PhysicalFileSystem(string virtualRoot) + { + if(HttpContext.Current == null) + throw new InvalidOperationException("The single parameter constructor can only be accessed when there is a valid HttpContext"); + + _rootPath = HttpContext.Current.Server.MapPath(virtualRoot); + _rootUrl = VirtualPathUtility.ToAbsolute(virtualRoot); + } + + public PhysicalFileSystem(string rootPath, string rootUrl) + { + if (string.IsNullOrEmpty(rootPath)) + throw new ArgumentException("The argument 'rootPath' cannot be null or empty."); + + if (string.IsNullOrEmpty(rootUrl)) + throw new ArgumentException("The argument 'rootUrl' cannot be null or empty."); + + _rootPath = rootPath; + _rootUrl = rootUrl; + } + + public override IEnumerable GetDirectories(string path) + { + path = EnsureTrailingSeparator(GetFullPath(path)); + + try + { + if (Directory.Exists(path)) + return Directory.EnumerateDirectories(path).Select(GetRelativePath); + } + catch (UnauthorizedAccessException ex) + { } + catch (DirectoryNotFoundException ex) + { } + + return Enumerable.Empty(); + } + + public override void DeleteDirectory(string path) + { + DeleteDirectory(path, false); + } + + public override void DeleteDirectory(string path, bool recursive) + { + if (!DirectoryExists(path)) + return; + + try + { + Directory.Delete(GetFullPath(path), recursive); + } + catch (DirectoryNotFoundException ex) + { } + } + + public override bool DirectoryExists(string path) + { + return Directory.Exists(GetFullPath(path)); + } + + public override void AddFile(string path, Stream stream) + { + AddFile(path, stream, true); + } + + public override void AddFile(string path, Stream stream, bool overrideIfExists) + { + if (FileExists(path) && !overrideIfExists) + throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", + path)); + + EnsureDirectory(Path.GetDirectoryName(path)); + + using (var destination = (Stream)File.Create(GetFullPath(path))) + stream.CopyTo(destination); + } + + public override IEnumerable GetFiles(string path) + { + return GetFiles(path, "*.*"); + } + + public override IEnumerable GetFiles(string path, string filter) + { + path = EnsureTrailingSeparator(GetFullPath(path)); + + try + { + if (Directory.Exists(path)) + return Directory.EnumerateFiles(path, filter).Select(GetRelativePath); + } + catch (UnauthorizedAccessException ex) + { } + catch (DirectoryNotFoundException ex) + { } + + return Enumerable.Empty(); + } + + public override Stream OpenFile(string path) + { + return File.OpenRead(GetFullPath(path)); + } + + public override void DeleteFile(string path) + { + if (!FileExists(path)) + return; + + try + { + File.Delete(GetFullPath(path)); + } + catch (FileNotFoundException ex) + { } + } + + public override bool FileExists(string path) + { + return File.Exists(GetFullPath(path)); + } + + public override string GetRelativePath(string fullPathOrUrl) + { + var relativePath = fullPathOrUrl + .TrimStart(_rootUrl) + .Replace('/', Path.DirectorySeparatorChar) + .TrimStart(_rootPath) + .TrimStart(Path.DirectorySeparatorChar); + + return relativePath; + } + + public override string GetFullPath(string path) + { + return !path.StartsWith(_rootPath) + ? Path.Combine(_rootPath, path) + : path; + } + + public override string GetUrl(string path) + { + return _rootUrl.TrimEnd("/") + "/" + path + .TrimStart(Path.DirectorySeparatorChar) + .Replace(Path.DirectorySeparatorChar, '/'); + } + + public override DateTimeOffset GetLastModified(string path) + { + return DirectoryExists(path) + ? new DirectoryInfo(GetFullPath(path)).LastWriteTimeUtc + : new FileInfo(GetFullPath(path)).LastWriteTimeUtc; + } + + public override DateTimeOffset GetCreated(string path) + { + return DirectoryExists(path) + ? Directory.GetCreationTimeUtc(GetFullPath(path)) + : File.GetCreationTimeUtc(GetFullPath(path)); + } + + #region Helper Methods + + protected virtual void EnsureDirectory(string path) + { + path = GetFullPath(path); + Directory.CreateDirectory(path); + } + + protected string EnsureTrailingSeparator(string path) + { + if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + path = path + Path.DirectorySeparatorChar; + + return path; + } + + #endregion + } +} diff --git a/src/Umbraco.Core/Properties/AssemblyInfo.cs b/src/Umbraco.Core/Properties/AssemblyInfo.cs index 66467357e9..8b45c29f7f 100644 --- a/src/Umbraco.Core/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Core/Properties/AssemblyInfo.cs @@ -26,3 +26,8 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("cms")] [assembly: InternalsVisibleTo("umbraco.editorControls")] [assembly: InternalsVisibleTo("umbraco.MacroEngines")] + +[assembly: InternalsVisibleTo("umbraco.editorControls")] +[assembly: InternalsVisibleTo("Umbraco.Tests")] + +[assembly: InternalsVisibleTo("Our.Umbraco.AmazonS3FileSystem")] diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 96ac25111b..725875506c 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -35,7 +35,7 @@ ..\packages\log4net.2.0.0\lib\net40-full\log4net.dll - + @@ -51,6 +51,9 @@ + + + @@ -95,6 +98,11 @@ + + + + + diff --git a/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs new file mode 100644 index 0000000000..5379dcd059 --- /dev/null +++ b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core.IO; +using Umbraco.Tests.BusinessLogic; + +namespace Umbraco.Tests.IO +{ + [TestFixture] + internal abstract class AbstractFileSystemTests + { + protected IFileSystem _fileSystem; + + protected AbstractFileSystemTests(IFileSystem fileSystem) + { + _fileSystem = fileSystem; + } + + [Test] + public void Can_Create_And_Delete_Files() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + Assert.IsTrue(_fileSystem.FileExists("test.txt")); + + _fileSystem.DeleteFile("test.txt"); + + Assert.IsFalse(_fileSystem.FileExists("test.txt")); + } + + [Test] + public void Can_Overwrite_File() + { + _fileSystem.AddFile("test/test.txt", CreateStream()); + _fileSystem.AddFile("test/test.txt", CreateStream()); + + var files = _fileSystem.GetFiles("test"); + + Assert.AreEqual(1, files.Count()); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void Cant_Overwrite_File() + { + _fileSystem.AddFile("test.txt", CreateStream()); + _fileSystem.AddFile("test.txt", CreateStream(), false); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Files() + { + _fileSystem.AddFile("test/test1.txt", CreateStream()); + _fileSystem.AddFile("test/test2.txt", CreateStream()); + _fileSystem.AddFile("test/test3.txt", CreateStream()); + _fileSystem.AddFile("test/test4.bak", CreateStream()); + + var files = _fileSystem.GetFiles("test"); + + Assert.AreEqual(4, files.Count()); + + files = _fileSystem.GetFiles("test", "*.txt"); + + Assert.AreEqual(3, files.Count()); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + public void Can_Read_File() + { + _fileSystem.AddFile("test.txt", CreateStream("hello world")); + + var stream = _fileSystem.OpenFile("test.txt"); + var reader = new StreamReader(stream); + var contents = reader.ReadToEnd(); + reader.Close(); + + Assert.AreEqual("hello world", contents); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Directories() + { + _fileSystem.AddFile("test/sub1/test.txt", CreateStream()); + _fileSystem.AddFile("test/sub2/test.txt", CreateStream()); + _fileSystem.AddFile("test/sub3/test.txt", CreateStream()); + + var dirs = _fileSystem.GetDirectories("test"); + + Assert.AreEqual(3, dirs.Count()); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub1")); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub2")); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub3")); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + public void Can_Get_File_Dates() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var created = _fileSystem.GetCreated("test.txt"); + var modified = _fileSystem.GetLastModified("test.txt"); + + Assert.AreEqual(DateTime.Today.Year, created.Year); + Assert.AreEqual(DateTime.Today.Month, created.Month); + Assert.AreEqual(DateTime.Today.Date, created.Date); + + Assert.AreEqual(DateTime.Today.Year, modified.Year); + Assert.AreEqual(DateTime.Today.Month, modified.Month); + Assert.AreEqual(DateTime.Today.Date, modified.Date); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_File_Url() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var url = _fileSystem.GetUrl("test.txt"); + + Assert.AreEqual(ConstructUrl("test.txt"), url); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Convert_Full_Path_And_Url_To_Relative_Path() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var url = _fileSystem.GetUrl("test.txt"); + var fullPath = _fileSystem.GetFullPath("test.txt"); + + Assert.AreNotEqual("test.txt", url); + Assert.AreNotEqual("test.txt", fullPath); + + Assert.AreEqual("test.txt", _fileSystem.GetRelativePath(url)); + Assert.AreEqual("test.txt", _fileSystem.GetRelativePath(fullPath)); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Size() + { + var stream = CreateStream(); + var streamLength = stream.Length; + _fileSystem.AddFile("test.txt", stream); + + Assert.AreEqual(streamLength, _fileSystem.GetSize("test.txt")); + + _fileSystem.DeleteFile("test.txt"); + } + + #region Helper Methods + + protected Stream CreateStream(string contents = null) + { + if(string.IsNullOrEmpty(contents)) + contents = "test"; + + var bytes = Encoding.UTF8.GetBytes(contents); + var stream = new MemoryStream(bytes); + + return stream; + } + + protected abstract string ConstructUrl(string path); + + #endregion + } +} diff --git a/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs b/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs new file mode 100644 index 0000000000..dc79f82620 --- /dev/null +++ b/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core.IO; +using Umbraco.Tests.BusinessLogic; + +namespace Umbraco.Tests.IO +{ + [TestFixture] + internal class PhysicalFileSystemTests : AbstractFileSystemTests + { + public PhysicalFileSystemTests() + : base(new PhysicalFileSystem(AppDomain.CurrentDomain.BaseDirectory, + "/Media/")) + { } + + protected override string ConstructUrl(string path) + { + return "/Media/" + path; + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 1ed1e7d4b3..6ff3fc2256 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -79,6 +79,8 @@ + + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 76be138a12..d86101b920 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -271,6 +271,9 @@ log4net.config + + + FileSystemProviders.config xsltExtensions.config diff --git a/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config b/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config new file mode 100644 index 0000000000..cffbc4e802 --- /dev/null +++ b/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/config/FileSystemProviders.config b/src/Umbraco.Web.UI/config/FileSystemProviders.config new file mode 100644 index 0000000000..cffbc4e802 --- /dev/null +++ b/src/Umbraco.Web.UI/config/FileSystemProviders.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config index 9384fc2c05..dae69d2df4 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config @@ -114,7 +114,6 @@ star - - ae oe aa @@ -125,8 +124,6 @@ ae oe - - false diff --git a/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx b/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx new file mode 100644 index 0000000000..3dab7a3f91 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" CodeBehind="MediaUploader.ashx.cs" Class="umbraco.presentation.umbraco.webservices.MediaUploader" %> diff --git a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js index cb380ba028..cdad318d0f 100644 --- a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js +++ b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js @@ -4,7 +4,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); (function ($, Base, window, document, undefined) { var itemMappingOptions = { - 'create': function(o) { + 'create': function (o) { var item = ko.mapping.fromJS(o.data); item.selected = ko.observable(false); item.toggleSelected = function (itm, e) { @@ -115,6 +115,14 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); items: ko.observableArray([]), queued: ko.observableArray([]) }); + + self._viewModel.filtered = ko.computed(function () { + return self._viewModel.items(); + return ko.utils.arrayFilter(this.items(), function (item) { + return item.Name().toLowerCase().indexOf(self._viewModel.filterTerm()) > -1 || + item.Tags().toLowerCase().indexOf(self._viewModel.filterTerm()) > -1; + }); + }, self._viewModel); self._viewModel.selected = ko.computed(function() { return ko.utils.arrayFilter(this.items(), function(item) { @@ -162,10 +170,10 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); var overlay = $("
" + "
" + instructions + - "
" + + "" + "" + "" + - "" + + "" + "
" + "
  • " + "" + @@ -173,8 +181,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); "" + "
" + "" + - "" + - "" + + "" + + "" + "Cancel" + "
" + "
"); @@ -226,6 +234,9 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); }, onProgress: function (data) { data.context.progress(data.progress); + }, + onDoneAll: function () { + self._getChildNodes(); } }); @@ -235,8 +246,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); $("#fileupload").fileUploader("uploadAll"); }); - $(".upload-overlay #overwriteExisting").click(function() { - $("input[name=overwriteExisting]").val($(this).is(":checked")); + $(".upload-overlay #replaceExisting").click(function() { + $("input[name=replaceExisting]").val($(this).is(":checked")); }); $(".upload-overlay .cancel").click(function (e) { @@ -301,15 +312,16 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); start: function (e, ui) { // Add dragging class to container $(".umbFolderBrowser .items").addClass("ui-sortable-dragging"); - - $(".umbFolderBrowser .items .ui-sortable-helper span").removeAttr("data-bind").text("Moving 1 item"); }, - update: function (e, ui) { + update: function (e, ui) + { + // Can't sort when filtered so just return + if (self._viewModel.filterTerm().length > 0) + return; + //var oldIndex = self._viewModel.items.indexOf(self._viewModel.tempItem()); var newIndex = ui.item.index(); - //TODO: Don't allow sorting on a filtered view - $(".umbFolderBrowser .items .selected").sort(function (a,b) { return parseInt($(a).data("order")) > parseInt($(b).data("order")) ? 1 : -1; }).each(function(idx, itm) { @@ -327,7 +339,15 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); stop: function (e, ui) { // Remove dragging class from container $(".umbFolderBrowser .items").removeClass("ui-sortable-dragging"); - //TODO: Update on server + + if (self._viewModel.filterTerm().length > 0) { + $(this).sortable("cancel"); + alert("Can't sort items which have been filtered"); + } + else + { + //TODO: Update on server + } } }); }, diff --git a/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js b/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js index da22f21a87..f3074ef21f 100644 --- a/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js +++ b/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js @@ -26,7 +26,7 @@ * @param {string} url Absolute URL to where the plugin is located. */ init: function (ed) { - var t = this; + if (ed.plugins.contextmenu) { ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { @@ -61,7 +61,7 @@ }); } - + } }); // Register plugin diff --git a/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config b/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config index 4b2e4bb8da..124bf94e8e 100644 --- a/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config @@ -17,9 +17,9 @@ + value="server=.\sqlexpress;database=481;user id=DBUSER;password=DBPASSWORD"/> + value="4.8.1"/> diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 0d9235e222..e3644f256d 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -13,6 +13,7 @@
+
@@ -29,6 +30,7 @@ + diff --git a/src/Umbraco.Web/Media/ThumbnailProviders/ImageThumbnailProvider.cs b/src/Umbraco.Web/Media/ThumbnailProviders/ImageThumbnailProvider.cs index 4e5ddbb489..5d117f1040 100644 --- a/src/Umbraco.Web/Media/ThumbnailProviders/ImageThumbnailProvider.cs +++ b/src/Umbraco.Web/Media/ThumbnailProviders/ImageThumbnailProvider.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using Umbraco.Core; +using Umbraco.Core.IO; using umbraco.IO; namespace Umbraco.Web.Media.ThumbnailProviders @@ -36,8 +37,19 @@ namespace Umbraco.Web.Media.ThumbnailProviders // Make sure the thumbnail exists var tmpThumbUrl = fileUrl.Replace(ext, "_thumb.jpg"); - if (!File.Exists(IOHelper.MapPath(tmpThumbUrl))) + + try + { + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); + var relativeThumbPath = fs.GetRelativePath(tmpThumbUrl); + if (!fs.FileExists(relativeThumbPath)) + return false; + } + catch (Exception) + { + // If something odd happens, just return false and move on return false; + } // We've got this far, so thumbnail must exist thumbUrl = tmpThumbUrl; diff --git a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs index 272d83c8bb..3b6db75e7b 100644 --- a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs +++ b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; using System.Text; +using System.Web; +using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using ClientDependency.Core; using umbraco.BasePages; +using umbraco.BusinessLogic; using umbraco.IO; using umbraco.cms.businesslogic.media; @@ -113,7 +116,7 @@ namespace Umbraco.Web.UI.Controls sb.Append("
Filter:
"); // Create thumbnails container - sb.Append("
    " + + sb.Append("
      " + "
    • " + "
    "); diff --git a/src/Umbraco.Web/WebServices/FolderBrowserService.cs b/src/Umbraco.Web/WebServices/FolderBrowserService.cs index 2c02c3dca0..3535b66894 100644 --- a/src/Umbraco.Web/WebServices/FolderBrowserService.cs +++ b/src/Umbraco.Web/WebServices/FolderBrowserService.cs @@ -45,19 +45,21 @@ namespace Umbraco.Web.WebServices var fileUrl = fileProp != null ? fileProp.Value.ToString() : ""; var thumbUrl = ThumbnailProvidersResolver.Current.GetThumbnailUrl(fileUrl); - - data.Add(new + var item = new { Id = child.Id, Path = child.Path, Name = child.Text, + Tags = string.Join(",", Tag.GetTags(child.Id).Select(x => x.TagCaption)), MediaTypeAlias = child.ContentType.Alias, EditUrl = string.Format("editMedia.aspx?id={0}", child.Id), FileUrl = fileUrl, - ThumbnailUrl = !string.IsNullOrEmpty(thumbUrl) - ? thumbUrl + ThumbnailUrl = !string.IsNullOrEmpty(thumbUrl) + ? thumbUrl : IOHelper.ResolveUrl(SystemDirectories.Umbraco + "/images/thumbnails/" + child.ContentType.Thumbnail) - }); + }; + + data.Add(item); } return new JavaScriptSerializer().Serialize(data); @@ -84,14 +86,6 @@ namespace Umbraco.Web.WebServices }); } - [RestExtensionMethod(returnXml = false)] - public static string Upload(int parentId) - { - return new JavaScriptSerializer().Serialize(new { - success = true - }); - } - [RestExtensionMethod(returnXml = false)] public static string UpdateSortOrder(int parentId, IDictionary map) { diff --git a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs index 0695c7c162..f5d8698001 100644 --- a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs @@ -8,6 +8,8 @@ using System.Xml; using System.Text.RegularExpressions; using Umbraco.Web; using Umbraco.Web.Routing; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; using umbraco.cms.businesslogic.web; using umbraco.cms.businesslogic; @@ -171,7 +173,6 @@ namespace umbraco if (ValidateRequest) Request.ValidateInput(); - // handle the infamous umbDebugShowTrace, etc Page.Trace.IsEnabled &= GlobalSettings.DebugMode && !String.IsNullOrWhiteSpace(Request["umbDebugShowTrace"]); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs index c33e843b17..4e19a87947 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs @@ -16,7 +16,7 @@ namespace umbraco /// /// RelationTypes tree for developer section /// - //[Tree("developer", "relationTypes", "Relation Types", sortOrder: 4)] + [Tree("developer", "relationTypes", "Relation Types", sortOrder: 4)] public class loadRelationTypes : BaseTree { /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs index 8c23e383a6..e2dc9302e3 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Text; using System.Web; using System.Web.Configuration; +using System.Web.Script.Serialization; using System.Web.Security; using System.Xml; +using System.Xml.Serialization; using umbraco.BusinessLogic; using umbraco.businesslogic.Exceptions; using umbraco.cms.businesslogic.media; @@ -25,75 +27,100 @@ namespace umbraco.presentation.umbraco.webservices public void ProcessRequest(HttpContext context) { - context.Response.Clear(); - context.Response.ContentType = @"text\xml"; - context.Response.Charset = "UTF-8"; - context.Response.Cache.SetCacheability(HttpCacheability.NoCache); - context.Response.Cache.SetAllowResponseInBrowserHistory(true); + MediaResponse response = null; - var xmlTextWriter = new XmlTextWriter(context.Response.OutputStream, Encoding.UTF8); - xmlTextWriter.WriteStartDocument(); - xmlTextWriter.WriteStartElement("response"); + var action = context.Request["action"]; - string action = context.Request["action"]; - - if (IsValidRequest(context, xmlTextWriter) && !string.IsNullOrEmpty(action)) + if (IsValidRequest(context) && !string.IsNullOrEmpty(action)) { switch (action.ToLower()) { case "config": - ProcessConfigRequest(context, xmlTextWriter); + response = ProcessConfigRequest(context); break; case "folderlist": - ProcessFolderListRequest(context, xmlTextWriter); + response = ProcessFolderListRequest(context); break; case "upload": - ProcessUploadRequest(context, xmlTextWriter); + response = ProcessUploadRequest(context); break; } } - xmlTextWriter.WriteEndElement(); - xmlTextWriter.WriteEndDocument(); - xmlTextWriter.Flush(); - xmlTextWriter.Close(); + // Set success flag + if (response != null) + response.success = true; + else + response = new MediaResponse { success = false }; + + context.Response.Clear(); + context.Response.Charset = "UTF-8"; + context.Response.Cache.SetCacheability(HttpCacheability.NoCache); + context.Response.Cache.SetAllowResponseInBrowserHistory(true); + + var format = context.Request["format"]; + switch (format) + { + case "json": + // Format as JSON + context.Response.ContentType = @"application/json"; + + context.Response.Write(new JavaScriptSerializer().Serialize(response)); + + break; + default: + // Format as XML + context.Response.ContentType = @"text/xml"; + + var serializer = new XmlSerializer(response.GetType()); + serializer.Serialize(context.Response.OutputStream, response); + + break; + } + context.Response.End(); } - public void ProcessConfigRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public ConfigResponse ProcessConfigRequest(HttpContext context) { - xmlTextWriter.WriteElementString("displayName", new User(context.Request["username"]).Name); - xmlTextWriter.WriteElementString("umbracoPath", VirtualPathUtility.ToAbsolute(GlobalSettings.Path)); - xmlTextWriter.WriteElementString("maxRequestLength", GetMaxRequestLength().ToString()); + return new ConfigResponse + { + displayName = new User(context.Request["username"]).Name, + umbracoPath = VirtualPathUtility.ToAbsolute(GlobalSettings.Path), + maxRequestLength = GetMaxRequestLength() + }; } - public void ProcessFolderListRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public FolderListResponse ProcessFolderListRequest(HttpContext context) { - xmlTextWriter.WriteStartElement("folder"); + var response = new FolderListResponse + { + folder = new FolderListItem() + }; var startMediaId = AuthenticatedUser.StartMediaId; if (startMediaId < 1) { - xmlTextWriter.WriteAttributeString("id", "-1"); - xmlTextWriter.WriteAttributeString("name", "Media"); + response.folder.id = -1; + response.folder.name = "Media"; - CreateMediaTree(Media.GetRootMedias(), xmlTextWriter); + CreateMediaTree(Media.GetRootMedias(), response.folder); } else { var root = new Media(startMediaId); - xmlTextWriter.WriteAttributeString("id", root.Id.ToString()); - xmlTextWriter.WriteAttributeString("name", root.Text); + response.folder.id = root.Id; + response.folder.name = root.Text; - CreateMediaTree(root.Children, xmlTextWriter); + CreateMediaTree(root.Children, response.folder); } - xmlTextWriter.WriteEndElement(); + return response; } - public void ProcessUploadRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public UploadResponse ProcessUploadRequest(HttpContext context) { int parentNodeId; if (int.TryParse(context.Request["parentNodeId"], out parentNodeId) && context.Request.Files.Count > 0) @@ -117,7 +144,8 @@ namespace umbraco.presentation.umbraco.webservices } // Check whether to replace existing - bool replaceExisting = (context.Request["replaceExisting"] == "1"); + var parsed = false; + bool replaceExisting = (context.Request["replaceExisting"] == "1" || (bool.TryParse(context.Request["replaceExisting"], out parsed) && parsed)); // loop through uploaded files for (var j = 0; j < context.Request.Files.Count; j++) @@ -131,16 +159,18 @@ namespace umbraco.presentation.umbraco.webservices var postedMediaFile = new PostedMediaFile { FileName = uploadFile.FileName, + DisplayName = context.Request["name"], ContentType = uploadFile.ContentType, ContentLength = uploadFile.ContentLength, - InputStream = uploadFile.InputStream + InputStream = uploadFile.InputStream, + ReplaceExisting = replaceExisting }; // Get concrete MediaFactory var factory = MediaFactory.GetMediaFactory(parentNodeId, postedMediaFile, AuthenticatedUser); // Handle media Item - var media = factory.HandleMedia(parentNodeId, postedMediaFile, AuthenticatedUser, replaceExisting); + var media = factory.HandleMedia(parentNodeId, postedMediaFile, AuthenticatedUser); } } @@ -158,11 +188,13 @@ namespace umbraco.presentation.umbraco.webservices // log error Log.Add(LogTypes.Error, -1, "Parent node id is in incorrect format"); } + + return new UploadResponse(); } #region Helper Methods - private bool IsValidRequest(HttpContext context, XmlTextWriter xmlTextWriter) + private bool IsValidRequest(HttpContext context) { // check for secure connection if (GlobalSettings.UseSSL && !context.Request.IsSecureConnection) @@ -195,26 +227,31 @@ namespace umbraco.presentation.umbraco.webservices if (isValid) AuthenticatedUser = user; } - - xmlTextWriter.WriteAttributeString("success", isValid.ToString().ToLower()); + else if (User.GetCurrent() != null) + { + isValid = true; + AuthenticatedUser = User.GetCurrent(); + } return isValid; } - private void CreateMediaTree(IEnumerable nodes, XmlWriter xmlTextWriter) + private void CreateMediaTree(IEnumerable nodes, FolderListItem folder) { foreach (var media in nodes.Where(media => media != null && media.ContentType != null && media.ContentType.Alias == "Folder")) { - xmlTextWriter.WriteStartElement("folder"); - xmlTextWriter.WriteAttributeString("id", media.Id.ToString()); - xmlTextWriter.WriteAttributeString("name", media.Text); + var subFolder = new FolderListItem + { + id = media.Id, + name = media.Text + }; if (media.HasChildren) { - CreateMediaTree(media.Children, xmlTextWriter); + CreateMediaTree(media.Children, subFolder); } - xmlTextWriter.WriteEndElement(); + folder.folders.Add(subFolder); } } @@ -266,4 +303,46 @@ namespace umbraco.presentation.umbraco.webservices #endregion } + + public class MediaResponse + { + [XmlAttribute] + public bool success { get; set; } + } + + [XmlRoot("response")] + public class ConfigResponse : MediaResponse + { + public string displayName { get; set; } + public string umbracoPath { get; set; } + public int maxRequestLength { get; set; } + } + + [XmlRoot("response")] + public class FolderListResponse : MediaResponse + { + public FolderListItem folder { get; set; } + } + + [XmlType("folder")] + public class FolderListItem + { + [XmlAttribute] + public int id { get; set; } + + [XmlAttribute] + public string name { get; set; } + + [XmlElement("folder")] + public List folders { get; set; } + + public FolderListItem() + { + folders = new List(); + } + } + + [XmlRoot("response")] + public class UploadResponse : MediaResponse + { } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs index b8f46be9b2..7ea5cc9928 100644 --- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs +++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs @@ -77,12 +77,19 @@ namespace umbraco.MacroEngines var contextWrapper = new HttpContextWrapper(context); //inject http context - for request response + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Context (file: {0})", macro.Name)); razorWebPage.Context = contextWrapper; + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Context (file: {0})", macro.Name)); //Inject Macro Model And Parameters if (razorWebPage is IMacroContext) { + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Boxing Macro Script MacroContext (file: {0})", macro.Name)); var razorMacro = (IMacroContext)razorWebPage; + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Boxing Macro Script MacroContext (file: {0})", macro.Name)); + + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Model (file: {0})", macro.Name)); razorMacro.SetMembers(macro, currentPage); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Model (file: {0})", macro.Name)); } } @@ -106,11 +113,16 @@ namespace umbraco.MacroEngines return String.Empty; //No File Location var razorWebPage = CompileAndInstantiate(fileLocation); + + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Context (file: {0})", macro.Name)); InjectContext(razorWebPage, macro, currentPage); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Context (file: {0})", macro.Name)); //Output Razor To String var output = new StringWriter(); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Executing Macro Script (file: {0})", macro.Name)); razorWebPage.ExecutePageHierarchy(new WebPageContext(contextWrapper, razorWebPage, null), output); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Executing Macro Script (file: {0})", macro.Name)); return output.ToString(); } diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs index a50c7a9aeb..ab555a587a 100644 --- a/src/umbraco.businesslogic/BasePages/BasePage.cs +++ b/src/umbraco.businesslogic/BasePages/BasePage.cs @@ -2,6 +2,7 @@ using System; using System.Data; using System.Web; using System.Linq; +using System.Web.Security; using umbraco.BusinessLogic; using umbraco.DataLayer; using umbraco.IO; @@ -227,7 +228,26 @@ namespace umbraco.BasePages if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue) return StateHelper.Cookies.UserContext.GetValue(); else - return ""; + { + try + { + string encTicket = StateHelper.Cookies.UserContext.GetValue(); + if (!String.IsNullOrEmpty(encTicket)) + return FormsAuthentication.Decrypt(encTicket).UserData; + } + catch (HttpException ex) + { + // we swallow this type of exception as it happens if a legacy (pre 4.8.1) cookie is set + } + catch (ArgumentException ex) + { + // we swallow this one because it's 99.99% certaincy is legacy based. We'll still log it, though + Log.Instance.AddException(ex); + + } + } + + return ""; } set { @@ -238,8 +258,28 @@ namespace umbraco.BasePages if (StateHelper.Cookies.UserContext.HasValue) StateHelper.Cookies.ClearAll(); - // Create new cookie. + if (!String.IsNullOrEmpty(value)) + { + FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, + value, + DateTime.Now, + DateTime.Now.AddDays(1), + false, + value, + FormsAuthentication.FormsCookiePath); + + // Encrypt the ticket. + string encTicket = FormsAuthentication.Encrypt(ticket); + + + // Create new cookie. StateHelper.Cookies.UserContext.SetValue(value, 1); + + + } else + { + StateHelper.Cookies.UserContext.Clear(); + } } } } diff --git a/src/umbraco.businesslogic/StateHelper.cs b/src/umbraco.businesslogic/StateHelper.cs index 607a729634..9bf45c0cfa 100644 --- a/src/umbraco.businesslogic/StateHelper.cs +++ b/src/umbraco.businesslogic/StateHelper.cs @@ -431,6 +431,8 @@ namespace umbraco.BusinessLogic public void SetValue(string value) { HttpCookie cookie = new HttpCookie(_key, value); + if (GlobalSettings.UseSSL) + cookie.Secure = true; if (!TimeSpan.Zero.Equals(_expires)) cookie.Expires = DateTime.Now + _expires; ResponseCookie = cookie; @@ -455,7 +457,9 @@ namespace umbraco.BusinessLogic public void SetValue(string value, DateTime expires) { HttpCookie cookie = new HttpCookie(_key, value); - cookie.Expires = expires; + if (GlobalSettings.UseSSL) + cookie.Secure = true; + cookie.Expires = expires; ResponseCookie = cookie; // original Umbraco code also does this diff --git a/src/umbraco.cms/businesslogic/Content.cs b/src/umbraco.cms/businesslogic/Content.cs index a94b6e45dc..fe7d5fdb25 100644 --- a/src/umbraco.cms/businesslogic/Content.cs +++ b/src/umbraco.cms/businesslogic/Content.cs @@ -512,6 +512,9 @@ namespace umbraco.cms.businesslogic Guid newVersion = Guid.NewGuid(); bool tempHasVersion = hasVersion(); + + // we need to ensure that a version in the db exist before we add related data + SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values (" + this.Id + ",'" + newVersion + "')"); foreach (propertytype.PropertyType pt in this.ContentType.PropertyTypes) { object oldValue = ""; @@ -526,7 +529,6 @@ namespace umbraco.cms.businesslogic property.Property p = this.addProperty(pt, newVersion); if (oldValue != null && oldValue.ToString() != "") p.Value = oldValue; } - SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values (" + this.Id + ",'" + newVersion + "')"); this.Version = newVersion; return newVersion; } diff --git a/src/umbraco.cms/businesslogic/Files/IFile.cs b/src/umbraco.cms/businesslogic/Files/IFile.cs index 7bfb4490f5..ccf858fb02 100644 --- a/src/umbraco.cms/businesslogic/Files/IFile.cs +++ b/src/umbraco.cms/businesslogic/Files/IFile.cs @@ -9,7 +9,10 @@ namespace umbraco.cms.businesslogic.Files { string Filename { get; } string Extension { get; } + [Obsolete("LocalName is obsolete, please use URL instead", false)] string LocalName { get; } + string Path { get; } + string Url { get; } bool SupportsResizing { get; } string GetFriendlyName(); System.Tuple GetDimensions(); diff --git a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs index 1328eb9892..a8f65839a2 100644 --- a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs +++ b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs @@ -6,109 +6,89 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Web; +using Umbraco.Core.IO; using Encoder = System.Text.Encoder; namespace umbraco.cms.businesslogic.Files { public class UmbracoFile : IFile { - private string _fullFilePath; + private string _path; private string _fileName; - private string _directoryName; private string _extension; - private string _localName; + private string _url; private long _length; + private IFileSystem _fs; + + #region Constructors + public UmbracoFile() { - + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); } - public UmbracoFile(string fullFilePath) + public UmbracoFile(string path) { - _fullFilePath = fullFilePath; + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); + + _path = path; + initialize(); } + + #endregion - public static UmbracoFile Save(HttpPostedFile file, string fullFileName) + #region Static Methods + + //MB: Do we really need all these overloads? looking through the code, only one of them is actually used + + public static UmbracoFile Save(HttpPostedFile file, string path) { - byte[] fileData = null; - using (var binaryReader = new BinaryReader(file.InputStream)) - { - fileData = binaryReader.ReadBytes(file.ContentLength); - } - - return Save(fileData, fullFileName); + return Save(file.InputStream, path); } - public static UmbracoFile Save(HttpPostedFileBase file, string fullFileName) + public static UmbracoFile Save(HttpPostedFileBase file, string path) { - byte[] fileData = null; - using (var binaryReader = new BinaryReader(file.InputStream)) - { - fileData = binaryReader.ReadBytes(file.ContentLength); - } - - return Save(fileData, fullFileName); + return Save(file.InputStream, path); } - public static UmbracoFile Save(Stream inputStream, string fullFileName){ - - byte[] fileData = null; - using (var binaryReader = new BinaryReader(inputStream)) - { - fileData = binaryReader.ReadBytes((int)inputStream.Length); - } + public static UmbracoFile Save(Stream inputStream, string path) + { + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); + fs.AddFile(path, inputStream); - return Save(fileData, fullFileName); + return new UmbracoFile(path); } - public static UmbracoFile Save(byte[] file, string fullFileName) + public static UmbracoFile Save(byte[] file, string relativePath) { - string fullFilePath = IO.IOHelper.MapPath(fullFileName); - - // create directories - DirectoryInfo di = new DirectoryInfo(IO.IOHelper.MapPath(fullFilePath.Substring(0, fullFilePath.LastIndexOf(Path.DirectorySeparatorChar)))); - if (!di.Exists) - { - var currentDir = IO.IOHelper.MapPath(IO.SystemDirectories.Root); - var rootDir = IO.IOHelper.MapPath(IO.SystemDirectories.Root); - foreach (var dir in di.FullName.Substring(rootDir.Length).Split(Path.DirectorySeparatorChar)) - { - currentDir = Path.Combine(currentDir, dir); - if (!new DirectoryInfo(currentDir).Exists) - { - Directory.CreateDirectory(currentDir); - } - } - } - - File.WriteAllBytes(fullFilePath, file); - return new UmbracoFile(fullFilePath); + return Save(new MemoryStream(file), relativePath); } public static UmbracoFile Save(HttpPostedFile file) { - string tempDir = Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); - return Save(file, tempDir); - } - //filebase overload... - public static UmbracoFile Save(HttpPostedFileBase file) - { - string tempDir = Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); + string tempDir = System.IO.Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); return Save(file, tempDir); } + //filebase overload... + public static UmbracoFile Save(HttpPostedFileBase file) + { + string tempDir = System.IO.Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); + return Save(file, tempDir); + } + + #endregion + private void initialize() { - var fi = new FileInfo(_fullFilePath); - _fileName = fi.Name; - _length = fi.Length; - _directoryName = fi.DirectoryName; - _extension = fi.Extension.Substring(1).ToLowerInvariant(); - _localName = - "/" + fi.FullName.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length).Replace( - Path.DirectorySeparatorChar.ToString(), "/"); + _fileName = System.IO.Path.GetFileName(_path); + _length = _fs.GetSize(_path); + _extension = System.IO.Path.GetExtension(_path) != null + ? System.IO.Path.GetExtension(_path).Substring(1).ToLowerInvariant() + : ""; + _url = _fs.GetUrl(_path); } #region IFile Members @@ -124,9 +104,20 @@ namespace umbraco.cms.businesslogic.Files get { return _extension; } } + [Obsolete("LocalName is obsolete, please use Url instead", false)] public string LocalName { - get { return _localName; } + get { return Url; } + } + + public string Path + { + get { return _path; } + } + + public string Url + { + get { return _url; } } public long Length @@ -155,11 +146,8 @@ namespace umbraco.cms.businesslogic.Files { throwNotAnImageException(); - - FileStream fs = new FileStream(_fullFilePath, - FileMode.Open, FileAccess.Read, FileShare.Read); - - Image image = Image.FromStream(fs); + var fs = _fs.OpenFile(_path); + var image = Image.FromStream(fs); var fileWidth = image.Width; var fileHeight = image.Height; fs.Close(); @@ -172,42 +160,43 @@ namespace umbraco.cms.businesslogic.Files { throwNotAnImageException(); - string fileNameThumb = DoResize(width, height, 0, String.Empty); + var fileNameThumb = DoResize(width, height, 0, String.Empty); - return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length); + return _fs.GetUrl(fileNameThumb); } public string Resize(int maxWidthHeight, string fileNameAddition) { throwNotAnImageException(); - string fileNameThumb = DoResize(GetDimensions().Item1, GetDimensions().Item2, maxWidthHeight, fileNameAddition); + var fileNameThumb = DoResize(GetDimensions().Item1, GetDimensions().Item2, maxWidthHeight, fileNameAddition); - return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length); + return _fs.GetUrl(fileNameThumb); } private string DoResize(int width, int height, int maxWidthHeight, string fileNameAddition) { - - FileStream fs = new FileStream(_fullFilePath, - FileMode.Open, FileAccess.Read, FileShare.Read); - Image image = Image.FromStream(fs); + var fs = _fs.OpenFile(_path); + var image = Image.FromStream(fs); fs.Close(); string fileNameThumb = String.IsNullOrEmpty(fileNameAddition) ? - string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf("."))) : - string.Format("{0}_{1}.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf(".")), fileNameAddition); - generateThumbnail( + string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", _path.Substring(0, _path.LastIndexOf("."))) : + string.Format("{0}_{1}.jpg", _path.Substring(0, _path.LastIndexOf(".")), fileNameAddition); + + fileNameThumb = generateThumbnail( image, maxWidthHeight, width, height, - _fullFilePath, + _path, _extension, fileNameThumb, maxWidthHeight == 0 - ); + ).FileName; + image.Dispose(); + return fileNameThumb; } @@ -220,7 +209,7 @@ namespace umbraco.cms.businesslogic.Files } - private System.Tuple generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName, bool useFixedDimensions) + private ResizedImage generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName, bool useFixedDimensions) { // Generate thumbnail float f = 1; @@ -267,14 +256,41 @@ namespace umbraco.cms.businesslogic.Files ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L); // Save the new image using the dimensions of the image - bp.Save(thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh)), codec, ep); + string newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", + string.Format("{0}x{1}", widthTh, heightTh)); + var ms = new MemoryStream(); + bp.Save(ms, codec, ep); + ms.Seek(0, 0); + + _fs.AddFile(newFileName, ms); + + ms.Close(); bp.Dispose(); g.Dispose(); - return new System.Tuple(widthTh, heightTh); + return new ResizedImage(widthTh, heightTh, newFileName); } } + + internal class ResizedImage + { + public ResizedImage() + { + + } + + public ResizedImage(int width, int height, string fileName) + { + Width = width; + Height = height; + FileName = fileName; + } + + public int Width { get; set; } + public int Height { get; set; } + public string FileName { get; set; } + } } diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index 5f2262cb6e..f399f9600b 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text.RegularExpressions; using System.Web; using System.Xml; using umbraco.cms.businesslogic.Files; @@ -32,13 +33,13 @@ namespace umbraco.cms.businesslogic.datatype if (value is HttpPostedFile) { var file = value as HttpPostedFile; - name = file.FileName; + name = SafeFileName(file.FileName.Substring(file.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, file.FileName.Length - file.FileName.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower()); fileStream = file.InputStream; } else if (value is HttpPostedFileBase) { var file = value as HttpPostedFileBase; - name = file.FileName; + name = SafeFileName(file.FileName.Substring(file.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, file.FileName.Length - file.FileName.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower()); fileStream = file.InputStream; } else if (value is HttpPostedFileWrapper) @@ -57,7 +58,7 @@ namespace umbraco.cms.businesslogic.datatype ? Path.Combine(PropertyId.ToString(), name) : PropertyId + "-" + name; - fileName = Path.Combine(SystemDirectories.Media, fileName); + //fileName = Path.Combine(SystemDirectories.Media, fileName); um = UmbracoFile.Save(fileStream, fileName); if (um.SupportsResizing) @@ -83,31 +84,34 @@ namespace umbraco.cms.businesslogic.datatype // check for auto fill of other properties (width, height, extension and filesize) string propertyTypeAlias = new Property(PropertyId).PropertyType.Alias; - XmlNode uploadFieldConfigNode = - UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( - string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); - if (uploadFieldConfigNode != null) + if (UmbracoSettings.ImageAutoFillImageProperties != null) { - // get the current document - Content content = Content.GetContentFromVersion(Version); - // only add dimensions to web images - if (um.SupportsResizing) + XmlNode uploadFieldConfigNode = + UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( + string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); + if (uploadFieldConfigNode != null) { - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", - um.GetDimensions().Item1); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", - um.GetDimensions().Item2); + // get the current document + Content content = Content.GetContentFromVersion(Version); + // only add dimensions to web images + if (um.SupportsResizing) + { + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", + um.GetDimensions().Item1); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", + um.GetDimensions().Item2); + } + else + { + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); + } + updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", um.Length); + updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", um.Extension); } - else - { - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); - } - updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", um.Length); - updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", um.Extension); } - base.Value = um.LocalName; + base.Value = um.Url; } else { @@ -126,21 +130,36 @@ namespace umbraco.cms.businesslogic.datatype } } + /// + /// 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. + private string SafeFileName(string filePath) + { + if (!String.IsNullOrEmpty(filePath)) + return Regex.Replace(filePath, @"[^a-zA-Z0-9\-\.\/\:]{1}", "_"); + return String.Empty; + } + private void clearRelatedValues() { string propertyTypeAlias = new Property(PropertyId).PropertyType.Alias; - XmlNode uploadFieldConfigNode = - UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( - string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); - if (uploadFieldConfigNode != null) + if (UmbracoSettings.ImageAutoFillImageProperties != null) { - // get the current document - Content content = Content.GetContentFromVersion(Version); - // only add dimensions to web images - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", String.Empty); + XmlNode uploadFieldConfigNode = + UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( + string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); + if (uploadFieldConfigNode != null) + { + // get the current document + Content content = Content.GetContentFromVersion(Version); + // only add dimensions to web images + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", String.Empty); + } } } diff --git a/src/umbraco.cms/businesslogic/media/IMediaFactory.cs b/src/umbraco.cms/businesslogic/media/IMediaFactory.cs index f3eb25d3e1..50c589765f 100644 --- a/src/umbraco.cms/businesslogic/media/IMediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/IMediaFactory.cs @@ -14,6 +14,8 @@ namespace umbraco.cms.businesslogic.media bool CanHandleMedia(int parentNodeId, PostedMediaFile postedFile, User user); Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user); + + [Obsolete("Use HandleMedia(int, PostedMediaFile, User) and set the ReplaceExisting property on PostedMediaFile instead")] Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting); } } diff --git a/src/umbraco.cms/businesslogic/media/MediaFactory.cs b/src/umbraco.cms/businesslogic/media/MediaFactory.cs index e4d583e1e8..a24a221fab 100644 --- a/src/umbraco.cms/businesslogic/media/MediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/MediaFactory.cs @@ -52,9 +52,11 @@ namespace umbraco.cms.businesslogic.media public class PostedMediaFile { public string FileName { get; set; } + public string DisplayName { get; set; } public string ContentType { get; set; } public int ContentLength { get; set; } public Stream InputStream { get; set; } + public bool ReplaceExisting { get; set; } public void SaveAs(string filename) { diff --git a/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs b/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs index b7f4560a99..bf916336fc 100644 --- a/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs @@ -31,17 +31,14 @@ namespace umbraco.cms.businesslogic.media } public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user) - { - return HandleMedia(parentNodeId, postedFile, user, false); - } - - public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting) { // Check to see if a file exists Media media; - string mediaName = extractTitleFromFileName(postedFile.FileName); + string mediaName = !string.IsNullOrEmpty(postedFile.DisplayName) + ? postedFile.DisplayName + : extractTitleFromFileName(postedFile.FileName); - if (replaceExisting && TryFindExistingMedia(parentNodeId, postedFile.FileName, out media)) + if (postedFile.ReplaceExisting && TryFindExistingMedia(parentNodeId, postedFile.FileName, out media)) { // Do nothing as existing media is returned } @@ -61,6 +58,14 @@ namespace umbraco.cms.businesslogic.media return media; } + [Obsolete("Use HandleMedia(int, PostedMediaFile, User) and set the ReplaceExisting property on PostedMediaFile instead")] + public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting) + { + postedFile.ReplaceExisting = replaceExisting; + + return HandleMedia(parentNodeId, postedFile, user); + } + public abstract void DoHandleMedia(Media media, PostedMediaFile uploadedFile, User user); #region Helper Methods diff --git a/src/umbraco.cms/businesslogic/relation/Relation.cs b/src/umbraco.cms/businesslogic/relation/Relation.cs index 66d95cab93..b0f6576f21 100644 --- a/src/umbraco.cms/businesslogic/relation/Relation.cs +++ b/src/umbraco.cms/businesslogic/relation/Relation.cs @@ -105,7 +105,7 @@ namespace umbraco.cms.businesslogic.relation public void Delete() { - SqlHelper.ExecuteNonQuery("delete from umbracoRelation where id = @id", SqlHelper.CreateParameter("@id", this.Id)); + SqlHelper.ExecuteNonQuery("DELETE FROM umbracoRelation WHERE id = @id", SqlHelper.CreateParameter("@id", this.Id)); } [MethodImpl(MethodImplOptions.Synchronized)] diff --git a/src/umbraco.cms/businesslogic/relation/RelationType.cs b/src/umbraco.cms/businesslogic/relation/RelationType.cs index c331235672..b31c6c6837 100644 --- a/src/umbraco.cms/businesslogic/relation/RelationType.cs +++ b/src/umbraco.cms/businesslogic/relation/RelationType.cs @@ -41,7 +41,7 @@ namespace umbraco.cms.businesslogic.relation public RelationType(int id) { using (IRecordsReader dr = SqlHelper.ExecuteReader( - "select id, dual, name, alias from umbracoRelationType where id = @id", SqlHelper.CreateParameter("@id", id))) + "SELECT id, [dual], name, alias FROM umbracoRelationType WHERE id = @id", SqlHelper.CreateParameter("@id", id))) { if (dr.Read()) { @@ -70,7 +70,7 @@ namespace umbraco.cms.businesslogic.relation { _name = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set name = @name where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@name", value)); + "UPDATE umbracoRelationType SET name = @name WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@name", value)); this.InvalidateCache(); } } @@ -82,7 +82,7 @@ namespace umbraco.cms.businesslogic.relation { _alias = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set alias = @alias where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@alias", value)); + "UPDATE umbracoRelationType SET alias = @alias WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@alias", value)); this.InvalidateCache(); } } @@ -94,7 +94,7 @@ namespace umbraco.cms.businesslogic.relation { _dual = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set [dual] = @dual where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@dual", value)); + "UPDATE umbracoRelationType SET [dual] = @dual WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@dual", value)); this.InvalidateCache(); } } @@ -128,7 +128,7 @@ namespace umbraco.cms.businesslogic.relation { var relationTypes = new List(); - using (IRecordsReader dr = SqlHelper.ExecuteReader("select id, dual, name, alias from umbracoRelationType")) + using (IRecordsReader dr = SqlHelper.ExecuteReader("SELECT id, [dual], name, alias FROM umbracoRelationType")) { while (dr.Read()) { diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 93e7d122ca..79352d52cd 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -646,7 +646,7 @@ namespace umbraco.cms.businesslogic.web { ArrayList docs = new ArrayList(); IRecordsReader dr = - SqlHelper.ExecuteReader("select distinct nodeId from cmsDocument where newest = 1 and not expireDate is null and expireDate <= @today", + SqlHelper.ExecuteReader("select distinct nodeId from cmsDocument where published = 1 and not expireDate is null and expireDate <= @today", SqlHelper.CreateParameter("@today", DateTime.Now)); while (dr.Read()) docs.Add(dr.GetInt("nodeId")); diff --git a/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs b/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs index d9b7861634..4b3fab9d0f 100644 --- a/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs +++ b/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs @@ -93,6 +93,7 @@ namespace umbraco.DataLayer.SqlHelpers.MySql switch (typeof(T).FullName) { case "System.Boolean": return (T)(object)((1).Equals(scalar)); + case "System.Guid": return (T)(object)(Guid.Parse(scalar.ToString())); default: return base.ConvertScalar(scalar); } } diff --git a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs index 816fc94a8d..882dbe19fa 100644 --- a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs +++ b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs @@ -171,7 +171,6 @@ namespace umbraco.DataLayer.Utility.Installer #endregion #region Protected Methods - protected virtual void NewInstall(string sql) { diff --git a/src/umbraco.datalayer/umbraco.datalayer.csproj b/src/umbraco.datalayer/umbraco.datalayer.csproj index b840213a13..34eccea3a4 100644 --- a/src/umbraco.datalayer/umbraco.datalayer.csproj +++ b/src/umbraco.datalayer/umbraco.datalayer.csproj @@ -23,7 +23,7 @@ 3.5 - v3.5 + v4.0 publish\ true Disk @@ -39,6 +39,7 @@ false false true + true diff --git a/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs b/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs index 770239a15e..b386ef6a51 100644 --- a/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs +++ b/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs @@ -326,10 +326,9 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol tempTag += " " + ide.Key.ToString() + "=\"" + ide.Value.ToString() + "\""; // Find the original filename, by removing the might added width and height + // NH, 4.8.1 - above replaced by loading the right media file from the db later! orgSrc = - IOHelper.ResolveUrl(orgSrc.Replace( - "_" + helper.FindAttribute(ht, "width") + "x" + helper.FindAttribute(ht, "height"), ""). - Replace("%20", " ")); + IOHelper.ResolveUrl(orgSrc.Replace("%20", " ")); // Check for either id or guid from media string mediaId = getIdFromSource(orgSrc, localMediaPath); @@ -358,15 +357,10 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol { try { - // Check extention - if (imageMedia.getProperty("umbracoExtension").Value.ToString() != orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1)) - orgSrc = orgSrc.Substring(0, orgSrc.LastIndexOf(".") + 1) + - imageMedia.getProperty("umbracoExtension").Value.ToString(); - // Format the tag tempTag = tempTag + " rel=\"" + imageMedia.getProperty("umbracoWidth").Value.ToString() + "," + - imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + orgSrc + + imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + IOHelper.ResolveUrl(imageMedia.getProperty("umbracoFile").Value.ToString()) + "\""; tempTag += "/>"; diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index 3d3a8faace..b531d399af 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -102,6 +102,10 @@ AllRules.ruleset + + {31785bc3-256c-4613-b2f5-a1b0bdded8c1} + Umbraco.Core + {651E1350-91B6-44B7-BD60-7207006D7003} Umbraco.Web @@ -176,6 +180,11 @@ + + + + + Code diff --git a/src/umbraco.editorControls/uploadfield/uploadField.cs b/src/umbraco.editorControls/uploadfield/uploadField.cs index f974bc4787..dbd0d6f46e 100644 --- a/src/umbraco.editorControls/uploadfield/uploadField.cs +++ b/src/umbraco.editorControls/uploadfield/uploadField.cs @@ -4,6 +4,7 @@ using System.Text.RegularExpressions; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; +using Umbraco.Core.IO; using umbraco.interfaces; using umbraco.IO; using Content = umbraco.cms.businesslogic.Content; @@ -18,8 +19,11 @@ namespace umbraco.editorControls private readonly String _thumbnails; private String _text; + private IFileSystem _fs; + public uploadField(IData Data, string ThumbnailSizes) { + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); _data = (cms.businesslogic.datatype.DefaultData) Data; _thumbnails = ThumbnailSizes; } @@ -107,8 +111,6 @@ namespace umbraco.editorControls // we update additional properties post image upload if (_data.Value != DBNull.Value && !string.IsNullOrEmpty(_data.Value.ToString())) { - string fullFilePath = IOHelper.MapPath(_data.Value.ToString()); - Content content = Content.GetContentFromVersion(_data.Version); // update extension in UI @@ -161,6 +163,7 @@ namespace umbraco.editorControls #endregion + [Obsolete("This method is now obsolete due to a change in the way that files are handled. If you need to check if a URL for an uploaded file is safe you should implement your own as this method will be removed in a future version", false)] public string SafeUrl(string url) { if (!String.IsNullOrEmpty(url)) @@ -176,27 +179,29 @@ namespace umbraco.editorControls Text = _data.Value.ToString(); } - private void deleteFile(string file) + private void deleteFile(string fileUrl) { - if (file.Length > 0) + if (fileUrl.Length > 0) { - // delete old file - if (File.Exists(IOHelper.MapPath(file))) - File.Delete(IOHelper.MapPath(file)); + var relativeFilePath = _fs.GetRelativePath(fileUrl); - string extension = (file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)); + // delete old file + if (_fs.FileExists(relativeFilePath)) + _fs.DeleteFile(relativeFilePath); + + string extension = (relativeFilePath.Substring(relativeFilePath.LastIndexOf(".") + 1, relativeFilePath.Length - relativeFilePath.LastIndexOf(".") - 1)); extension = extension.ToLower(); //check for thumbnails if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) { //delete thumbnails - string thumbnailfile = file.Replace("." + extension, "_thumb"); + string relativeThumbFilePath = relativeFilePath.Replace("." + extension, "_thumb"); try { - if (File.Exists(IOHelper.MapPath(thumbnailfile + _thumbnailext))) - File.Delete(IOHelper.MapPath(thumbnailfile + _thumbnailext)); + if (_fs.FileExists(relativeThumbFilePath + _thumbnailext)) + _fs.DeleteFile(relativeThumbFilePath + _thumbnailext); } catch { @@ -209,12 +214,12 @@ namespace umbraco.editorControls { if (thumb != "") { - string thumbnailextra = thumbnailfile + "_" + thumb + _thumbnailext; + string relativeExtraThumbFilePath = relativeThumbFilePath + "_" + thumb + _thumbnailext; try { - if (File.Exists(IOHelper.MapPath(thumbnailextra))) - File.Delete(IOHelper.MapPath(thumbnailextra)); + if (_fs.FileExists(relativeExtraThumbFilePath)) + _fs.DeleteFile(relativeExtraThumbFilePath); } catch { @@ -268,17 +273,18 @@ namespace umbraco.editorControls { if (!string.IsNullOrEmpty(Text)) { - string ext = _text.Substring(_text.LastIndexOf(".") + 1, _text.Length - _text.LastIndexOf(".") - 1); - string fileNameThumb = _text.Replace("." + ext, "_thumb.jpg"); - bool hasThumb = false; + var relativeFilePath = _fs.GetRelativePath(_text); + var ext = relativeFilePath.Substring(relativeFilePath.LastIndexOf(".") + 1, relativeFilePath.Length - relativeFilePath.LastIndexOf(".") - 1); + var relativeThumbFilePath = relativeFilePath.Replace("." + ext, "_thumb.jpg"); + var hasThumb = false; try { - hasThumb = File.Exists(IOHelper.MapPath(IOHelper.FindFile(fileNameThumb))); + hasThumb = _fs.FileExists(relativeThumbFilePath); // 4.8.0 added support for png thumbnails (but for legacy it might have been jpg - hence the check before) if (!hasThumb && (ext == "gif" || ext == "png")) { - fileNameThumb = _text.Replace("." + ext, "_thumb.png"); - hasThumb = File.Exists(IOHelper.MapPath(IOHelper.FindFile(fileNameThumb))); + relativeThumbFilePath = relativeFilePath.Replace("." + ext, "_thumb.png"); + hasThumb = _fs.FileExists(relativeThumbFilePath); } } catch @@ -286,17 +292,19 @@ namespace umbraco.editorControls } if (hasThumb) { - var thumb = new Image(); - thumb.ImageUrl = fileNameThumb; - thumb.BorderStyle = BorderStyle.None; + var thumb = new Image + { + ImageUrl = _fs.GetUrl(relativeThumbFilePath), + BorderStyle = BorderStyle.None + }; - output.WriteLine(""); + output.WriteLine(""); thumb.RenderControl(output); output.WriteLine("
    "); } else - output.WriteLine("" + - IOHelper.FindFile(Text) + "
    "); + output.WriteLine("" + + _fs.GetUrl(relativeFilePath) + "
    "); output.WriteLine("