diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs index 92bf338f5d..14d7b5d1e2 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs @@ -11,19 +11,6 @@ namespace Microsoft.AspNetCore.Builder { public static void UseVirtualFiles(this IApplicationBuilder app) { - //var options = app.ApplicationServices.GetRequiredService>().Value; - //var hostingEnvironment = app.ApplicationServices.GetRequiredService(); - - //var fileProvider = new FileProviderSubFolderWrapper( - // new CompositeFileProvider( - // new PhysicalFileProvider(hostingEnvironment.ContentRootPath), - // app.ApplicationServices.GetRequiredService() - // ), - // "/wwwroot", - // options.AllowedExtraWebContentFolders.ToArray(), - // options.AllowedExtraWebContentFileExtensions.ToArray() - //); - app.UseStaticFiles( new StaticFileOptions { diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/FileProviderSubFolderWrapper.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/FileProviderSubFolderWrapper.cs deleted file mode 100644 index ca5b1fe879..0000000000 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/FileProviderSubFolderWrapper.cs +++ /dev/null @@ -1,82 +0,0 @@ -//using System; -//using System.Linq; -//using JetBrains.Annotations; -//using Microsoft.Extensions.FileProviders; -//using Microsoft.Extensions.Primitives; - -//namespace Volo.Abp.VirtualFileSystem -//{ -// //TODO: Ensure that merging such subfolders is secure! (anyone can add /.. to the beginning!)..? - -// public class FileProviderSubFolderWrapper : IFileProvider -// { -// private readonly IFileProvider _fileProvider; -// private readonly string _rootPath; -// private readonly string[] _allowedExtraFolders; -// private readonly string[] _allowedExtraFileExtensions; - -// public FileProviderSubFolderWrapper( -// IFileProvider fileProvider, -// string rootPath, -// string[] allowedExtraFolders = null, -// string[] allowedExtraFileExtensions = null) -// { -// _fileProvider = fileProvider; -// _rootPath = rootPath; -// _allowedExtraFileExtensions = allowedExtraFileExtensions ?? Array.Empty(); -// _allowedExtraFolders = allowedExtraFolders ?? Array.Empty(); -// } - -// public IFileInfo GetFileInfo(string subpath) -// { -// Check.NotNullOrEmpty(subpath, nameof(subpath)); - -// if (ExtraAllowedPath(subpath)) -// { -// var fileInfo = _fileProvider.GetFileInfo(subpath); -// if (fileInfo.Exists) -// { -// return fileInfo; -// } -// } - -// return _fileProvider.GetFileInfo(_rootPath + subpath); -// } - -// public IDirectoryContents GetDirectoryContents([NotNull] string subpath) -// { -// Check.NotNullOrEmpty(subpath, nameof(subpath)); - -// if (ExtraAllowedPath(subpath)) -// { -// var directory = _fileProvider.GetDirectoryContents(subpath); -// if (directory.Exists) -// { -// return directory; -// } -// } - -// return _fileProvider.GetDirectoryContents(_rootPath + subpath); -// } - -// private bool ExtraAllowedPath(string path) -// { -// return ExtraAllowedFolder(path) && ExtraAllowedExtension(path); -// } - -// private bool ExtraAllowedFolder(string path) -// { -// return _allowedExtraFolders.Any(s => path.StartsWith(s, StringComparison.OrdinalIgnoreCase)); -// } - -// private bool ExtraAllowedExtension(string path) -// { -// return _allowedExtraFileExtensions.Any(e => path.EndsWith(e, StringComparison.OrdinalIgnoreCase)); -// } - -// public IChangeToken Watch(string filter) -// { -// return _fileProvider.Watch(filter); //TODO: Why this does not use NormalizePath? -// } -// } -//} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/PathUtils.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/PathUtils.cs new file mode 100644 index 0000000000..379091297b --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/PathUtils.cs @@ -0,0 +1,41 @@ +using System.IO; +using Microsoft.Extensions.Primitives; + +namespace Volo.Abp.AspNetCore.VirtualFileSystem +{ + /* Inspired from the Microsoft.Extensions.FileProviders.Physical package. */ + internal static class PathUtils + { + private static readonly char[] PathSeparators = {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}; + + public static bool PathNavigatesAboveRoot(string path) + { + var tokenizer = new StringTokenizer(path, PathSeparators); + var depth = 0; + + foreach (var segment in tokenizer) + { + if (segment.Equals(".") || segment.Equals("")) + { + continue; + } + + if (segment.Equals("..")) + { + depth--; + + if (depth == -1) + { + return true; + } + } + else + { + depth++; + } + } + + return false; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs index 3ac429853f..b837007996 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs @@ -10,13 +10,12 @@ using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.AspNetCore.VirtualFileSystem { - //TODO: How to handle wwwroot naming? public class WebContentFileProvider : IWebContentFileProvider, ISingletonDependency { private readonly IVirtualFileProvider _virtualFileProvider; private readonly IFileProvider _fileProvider; private readonly IHostingEnvironment _hostingEnvironment; - private string _rootPath = "/wwwroot"; + private string _rootPath = "/wwwroot"; //TODO: How to handle wwwroot naming? protected AspNetCoreContentOptions Options { get; } @@ -29,13 +28,18 @@ namespace Volo.Abp.AspNetCore.VirtualFileSystem _hostingEnvironment = hostingEnvironment; Options = options.Value; - _fileProvider = CreateHybridProvider(); + _fileProvider = CreateFileProvider(); } - public IFileInfo GetFileInfo(string subpath) + public virtual IFileInfo GetFileInfo(string subpath) { Check.NotNullOrEmpty(subpath, nameof(subpath)); + if (PathUtils.PathNavigatesAboveRoot(subpath)) + { + return new NotFoundFileInfo(subpath); + } + if (ExtraAllowedFolder(subpath) && ExtraAllowedExtension(subpath)) { var fileInfo = _fileProvider.GetFileInfo(subpath); @@ -48,10 +52,15 @@ namespace Volo.Abp.AspNetCore.VirtualFileSystem return _fileProvider.GetFileInfo(_rootPath + subpath); } - public IDirectoryContents GetDirectoryContents([NotNull] string subpath) + public virtual IDirectoryContents GetDirectoryContents([NotNull] string subpath) { Check.NotNullOrEmpty(subpath, nameof(subpath)); + if (PathUtils.PathNavigatesAboveRoot(subpath)) + { + return NotFoundDirectoryContents.Singleton; + } + if (ExtraAllowedFolder(subpath)) { var directory = _fileProvider.GetDirectoryContents(subpath); @@ -80,7 +89,7 @@ namespace Volo.Abp.AspNetCore.VirtualFileSystem ); } - protected virtual IFileProvider CreateHybridProvider() + protected virtual IFileProvider CreateFileProvider() { return new CompositeFileProvider( new PhysicalFileProvider(_hostingEnvironment.ContentRootPath),