Adding string file and folder name validation to FileSystemStorageProvider, so that MediaLibrary components don't need to do it separately

This commit is contained in:
Benedek Farkas 2024-04-08 17:45:25 +02:00
parent d3e02cdc46
commit 7aa946d53b
4 changed files with 49 additions and 28 deletions

View File

@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Localization;
@ -69,14 +68,8 @@ namespace Orchard.MediaLibrary.Controllers {
}
try {
bool valid = String.IsNullOrWhiteSpace(viewModel.Name) || Regex.IsMatch(viewModel.Name, @"^[^:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+$");
if (!valid) {
throw new ArgumentException(T("Folder contains invalid characters").ToString());
}
else {
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder created"));
}
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder created"));
}
catch (ArgumentException argumentException) {
Services.Notifier.Error(T("Creating Folder failed: {0}", argumentException.Message));
@ -136,14 +129,8 @@ namespace Orchard.MediaLibrary.Controllers {
}
try {
bool valid = String.IsNullOrWhiteSpace(viewModel.Name) || Regex.IsMatch(viewModel.Name, @"^[^:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+$");
if (!valid) {
throw new ArgumentException(T("Folder contains invalid characters").ToString());
}
else {
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder renamed"));
}
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder renamed"));
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing Folder failed: {0}", exception.Message));

View File

@ -67,8 +67,8 @@ namespace Orchard.MediaLibrary.MediaFileName
catch (OrchardException) {
updater.AddModelError("MediaFileNameEditorSettings.FileName", T("Unable to rename file. Invalid Windows file path."));
}
catch (Exception) {
updater.AddModelError("MediaFileNameEditorSettings.FileName", T("Unable to rename file"));
catch (Exception ex) {
updater.AddModelError("MediaFileNameEditorSettings.FileName", T("Unable to rename file: {0}", ex.Message));
}
}
}

View File

@ -21,7 +21,6 @@ namespace Orchard.MediaLibrary.Services {
private readonly IStorageProvider _storageProvider;
private readonly IEnumerable<IMediaFactorySelector> _mediaFactorySelectors;
private readonly IMediaFolderProvider _mediaFolderProvider;
private static char[] HttpUnallowed = new char[] { '<', '>', '*', '%', '&', ':', '\\', '?', '#' };
public MediaLibraryService(
IOrchardServices orchardServices,
@ -145,12 +144,6 @@ namespace Orchard.MediaLibrary.Services {
}
public string GetUniqueFilename(string folderPath, string filename) {
// remove any char which is unallowed in an HTTP request
foreach (var unallowedChar in HttpUnallowed) {
filename = filename.Replace(unallowedChar.ToString(), "");
}
// compute a unique filename
var uniqueFilename = filename;
var index = 1;

View File

@ -4,15 +4,22 @@ using System.IO;
using System.Linq;
using System.Web.Hosting;
using Orchard.Environment.Configuration;
using Orchard.Localization;
using Orchard.Validation;
using Orchard.Exceptions;
using Orchard.Localization;
using Orchard.Utility.Extensions;
using Orchard.Validation;
namespace Orchard.FileSystems.Media {
public class FileSystemStorageProvider : IStorageProvider {
private readonly string _storagePath; // c:\orchard\media\default
private readonly string _virtualPath; // ~/Media/Default/
private readonly string _publicPath; // /Orchard/Media/Default/
public static readonly char[] HttpUnallowedCharacters =
new char[] { '<', '>', '*', '%', '&', ':', '\\', '/', '?', '#', '"', '{', '}', '|', '^', '[', ']', '`' };
public static readonly char[] InvalidFolderNameCharacters =
Path.GetInvalidPathChars().Union(HttpUnallowedCharacters).ToArray();
public static readonly char[] InvalidFileNameCharacters =
Path.GetInvalidFileNameChars().Union(HttpUnallowedCharacters).ToArray();
public FileSystemStorageProvider(ShellSettings settings) {
var mediaPath = HostingEnvironment.IsHosted
@ -215,6 +222,13 @@ namespace Orchard.FileSystems.Media {
/// <param name="path">The relative path to the folder to be created.</param>
/// <exception cref="ArgumentException">If the folder already exists.</exception>
public void CreateFolder(string path) {
// We are dealing with a folder here, but GetFileName returns the last path segment, which in this case is
// the folder name.
if (FolderNameContainsInvalidCharacters(Path.GetFileName(path), out var invalidCharacters)) {
throw new ArgumentException(
T("The directory name contains invalid character(s): {0}", string.Join(", ", invalidCharacters)).ToString());
}
DirectoryInfo directoryInfo = new DirectoryInfo(MapStorage(path));
if (directoryInfo.Exists) {
throw new ArgumentException(T("Directory {0} already exists", path).ToString());
@ -248,6 +262,13 @@ namespace Orchard.FileSystems.Media {
throw new ArgumentException(T("Directory {0} does not exist", oldPath).ToString());
}
// We are dealing with a folder here, but GetFileName returns the last path segment, which in this case is
// the folder name.
if (FolderNameContainsInvalidCharacters(Path.GetFileName(newPath), out var invalidCharacters)) {
throw new ArgumentException(
T("The new directory name contains invalid character(s): {0}", string.Join(", ", invalidCharacters)).ToString());
}
DirectoryInfo targetDirectory = new DirectoryInfo(MapStorage(newPath));
if (targetDirectory.Exists) {
throw new ArgumentException(T("Directory {0} already exists", newPath).ToString());
@ -313,6 +334,11 @@ namespace Orchard.FileSystems.Media {
throw new ArgumentException(T("File {0} does not exist", oldPath).ToString());
}
if (FileNameContainsInvalidCharacters(Path.GetFileName(newPath), out var invalidCharacters)) {
throw new ArgumentException(
T("The new file name contains invalid character(s): {0}", string.Join(", ", invalidCharacters)).ToString());
}
FileInfo targetFileInfo = new FileInfo(MapStorage(newPath));
if (targetFileInfo.Exists) {
throw new ArgumentException(T("File {0} already exists", newPath).ToString());
@ -342,6 +368,11 @@ namespace Orchard.FileSystems.Media {
/// <exception cref="ArgumentException">If the file already exists.</exception>
/// <returns>The created file.</returns>
public IStorageFile CreateFile(string path) {
if (FileNameContainsInvalidCharacters(Path.GetFileName(path), out var invalidCharacters)) {
throw new ArgumentException(
T("The file name contains invalid character(s): {0}", string.Join(", ", invalidCharacters)).ToString());
}
FileInfo fileInfo = new FileInfo(MapStorage(path));
if (fileInfo.Exists) {
throw new ArgumentException(T("File {0} already exists", fileInfo.Name).ToString());
@ -427,6 +458,16 @@ namespace Orchard.FileSystems.Media {
return (di.Attributes & FileAttributes.Hidden) != 0;
}
public static bool FolderNameContainsInvalidCharacters(string folderName, out char[] invalidCharacters) {
invalidCharacters = folderName.Distinct().Intersect(InvalidFolderNameCharacters).ToArray();
return invalidCharacters.Any();
}
public static bool FileNameContainsInvalidCharacters(string folderName, out char[] invalidCharacters) {
invalidCharacters = folderName.Distinct().Intersect(InvalidFileNameCharacters).ToArray();
return invalidCharacters.Any();
}
#endregion
private class FileSystemStorageFile : IStorageFile {