using System.IO; using System.Linq; using System.Net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Trees; using Umbraco.Extensions; namespace Umbraco.Cms.Web.BackOffice.Trees { [Tree(Constants.Applications.Settings, "staticFiles", TreeTitle = "Static Files", TreeUse = TreeUse.Dialog)] public class StaticFilesTreeController : TreeController { private readonly IFileSystem _fileSystem; private const string AppPlugins = "App_Plugins"; private const string Webroot = "wwwroot"; public StaticFilesTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IEventAggregator eventAggregator, IPhysicalFileSystem fileSystem) : base(localizedTextService, umbracoApiControllerTypeCollection, eventAggregator) { _fileSystem = fileSystem; } protected override ActionResult GetTreeNodes(string id, FormCollection queryStrings) { var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString ? WebUtility.UrlDecode(id).TrimStart("/") : ""; var nodes = new TreeNodeCollection(); var directories = _fileSystem.GetDirectories(path); foreach (var directory in directories) { // We don't want any other directories under the root node other than the ones serving static files - App_Plugins and wwwroot if (id == Constants.System.RootString && directory != AppPlugins && directory != Webroot) { continue; } var hasChildren = _fileSystem.GetFiles(directory).Any() || _fileSystem.GetDirectories(directory).Any(); var name = Path.GetFileName(directory); var node = CreateTreeNode(WebUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren); if (node != null) { nodes.Add(node); } } // Only get the files inside App_Plugins and wwwroot var files = _fileSystem.GetFiles(path).Where(x => x.StartsWith(AppPlugins) || x.StartsWith(Webroot)); foreach (var file in files) { var name = Path.GetFileName(file); var node = CreateTreeNode(WebUtility.UrlEncode(file), path, queryStrings, name, "icon-document", false); if (node != null) { nodes.Add(node); } } return nodes; } // We don't have any menu item options (such as create/delete/reload) & only use the root node to load a custom UI protected override ActionResult GetMenuForNode(string id, FormCollection queryStrings) => null; } }