diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 4c2d0adbc6..b35264d752 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -45,11 +45,11 @@ namespace Umbraco.Core.IO public IEnumerable GetThumbnails(string path) { - var parentDirectory = System.IO.Path.GetDirectoryName(path); - var extension = System.IO.Path.GetExtension(path); + var parentDirectory = Path.GetDirectoryName(path); + var extension = Path.GetExtension(path); return GetFiles(parentDirectory) - .Where(x => x.StartsWith(path.TrimEnd(extension) + "_thumb")) + .Where(x => x.StartsWith(path.TrimEnd(extension) + "_thumb") || x.StartsWith(path.TrimEnd(extension) + "_big-thumb")) .ToList(); } @@ -57,7 +57,7 @@ namespace Umbraco.Core.IO { DeleteFile(path); - if (!deleteThumbnails) + if (deleteThumbnails == false) return; DeleteThumbnails(path); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index 5e260f93ee..e56af95054 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -100,6 +100,10 @@ function valPropertyMsg(serverValidationManager) { // based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg // is the only one, then we'll clear. + if (!newValue) { + return; + } + var errCount = 0; for (var e in formCtrl.$error) { if (e) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js index 95ed124517..cd3b24da4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js @@ -72,7 +72,7 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag //listen for clear files changes to set our model to be sent up to the server $scope.$watch("clearFiles", function (isCleared) { if (isCleared == true) { - $scope.model.value = "{clearFiles: true}"; + $scope.model.value = {clearFiles: true}; clearFiles(); } else { @@ -98,8 +98,8 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag $scope.clearFiles = false; //set the model value to be the concatenation of files selected. Please see the notes // in the description of this controller, it states that this value isn't actually used for persistence, - // but we need to set it to something so that the editor and the server can detect that it's been changed. - $scope.model.value = "{selectedFiles: '" + newVal.trimEnd(",") + "'}"; + // but we need to set it so that the editor and the server can detect that it's been changed, and it is used for validation. + $scope.model.value = { selectedFiles: newVal.trimEnd(",") }; }); }); @@ -113,9 +113,13 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag // has changed the value. There's only 2 scenarios where we change the value internall so // we know what those values can be, if they are not either of them, then we'll re-initialize. - if (newVal !== "{clearFiles: true}" && newVal !== $scope.originalValue && !newVal.startsWith("{selectedFiles:")) { + if (newVal.clearFiles !== true && newVal !== $scope.originalValue && !newVal.selectedFiles) { initialize($scope.rebuildInput.index + 1); } + + //if (newVal !== "{clearFiles: true}" && newVal !== $scope.originalValue && !newVal.startsWith("{selectedFiles:")) { + // initialize($scope.rebuildInput.index + 1); + //} } }); diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs index b236d55984..c03b7cf39e 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Drawing; +using System.IO; using System.Linq; using System.Xml; using Newtonsoft.Json.Linq; @@ -12,6 +14,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using umbraco; namespace Umbraco.Web.PropertyEditors { @@ -37,14 +40,9 @@ namespace Umbraco.Web.PropertyEditors /// protected override PropertyValueEditor CreateValueEditor() { - //TODO: Ensure we assign custom validation for uploaded file types! - - var baseEditor = base.CreateValueEditor(); - - return new FileUploadPropertyValueEditor - { - View = baseEditor.View - }; + var baseEditor = base.CreateValueEditor(); + baseEditor.Validators.Add(new UploadFileTypeValidator()); + return new FileUploadPropertyValueEditor(baseEditor); } protected override PreValueEditor CreatePreValueEditor() @@ -179,4 +177,39 @@ namespace Umbraco.Web.PropertyEditors } } + + internal class UploadFileTypeValidator : IPropertyValidator + { + public IEnumerable Validate(object value, PreValueCollection preValues, PropertyEditor editor) + { + + //now check the file type + var asJson = value as JObject; + if (asJson == null) yield break; + if (asJson["selectedFiles"] == null) yield break; + var fileNames = asJson["selectedFiles"].ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var fileName in fileNames) + { + if (ValidateFileExtension(fileName) == false) + { + yield return new ValidationResult(ui.Text("errors", "dissallowedMediaType"), + new[] + { + //we only store a single value for this editor so the 'member' or 'field' + // we'll associate this error with will simply be called 'value' + "value" + }); + } + } + + } + + internal static bool ValidateFileExtension(string fileName) + { + if (fileName.IndexOf('.') <= 0) return false; + var extension = Path.GetExtension(fileName).TrimStart("."); + return UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false; + } + + } } diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs index 681ffba662..2826c6c222 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -22,8 +22,11 @@ namespace Umbraco.Web.PropertyEditors /// /// The editor for the file upload property editor /// - internal class FileUploadPropertyValueEditor : PropertyValueEditor + internal class FileUploadPropertyValueEditor : PropertyValueEditorWrapper { + public FileUploadPropertyValueEditor(PropertyValueEditor wrapped) : base(wrapped) + { + } /// /// Overrides the deserialize value so that we can save the file accordingly @@ -68,9 +71,15 @@ namespace Umbraco.Web.PropertyEditors var newValue = new List(); + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); + if (clear) { - //TODO: Need to delete our old files! + //Remove any files that are saved for this item + foreach (var toRemove in currentPersistedValues) + { + fs.DeleteFile(fs.GetRelativePath(toRemove), true); + } return ""; } @@ -80,14 +89,20 @@ namespace Umbraco.Web.PropertyEditors var files = editorValue.AdditionalData["files"] as IEnumerable; if (files != null) { - var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); - //now we just need to move the files to where they should be var filesAsArray = files.ToArray(); + //a list of all of the newly saved files so we can compare with the current saved files and remove the old ones + var savedFilePaths = new List(); for (var i = 0; i < filesAsArray.Length; i++) { var file = filesAsArray[i]; + //don't continue if this is not allowed! + if (UploadFileTypeValidator.ValidateFileExtension(file.FileName) == false) + { + continue; + } + //TODO: ALl of this naming logic needs to be put into the ImageHelper and then we need to change ContentExtensions to do the same! var currentPersistedFile = currentPersistedValues.Length >= (i + 1) @@ -138,13 +153,19 @@ namespace Umbraco.Web.PropertyEditors } newValue.Add(umbracoFile.Url); + //add to the saved paths + savedFilePaths.Add(umbracoFile.Url); } //now remove the temp file - File.Delete(file.TempFilePath); + File.Delete(file.TempFilePath); + } + + //Remove any files that are no longer saved for this item + foreach (var toRemove in currentPersistedValues.Except(savedFilePaths)) + { + fs.DeleteFile(fs.GetRelativePath(toRemove), true); } - //TODO: We need to remove any files that were previously persisted but are no longer persisted. FOr example, if we - // uploaded 5 files before and then only uploaded 3, then the last two should be deleted. return string.Join(",", newValue); }