Merge pull request #464 from sbwalker/master
validate folder names, handle missing files more gracefully
This commit is contained in:
		@ -149,10 +149,16 @@
 | 
			
		||||
                {
 | 
			
		||||
                    folder = await FolderService.AddFolderAsync(folder);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
 | 
			
		||||
                await logger.LogInformation("Folder Saved {Folder}", folder);
 | 
			
		||||
                NavigationManager.NavigateTo(NavigateUrl());
 | 
			
		||||
                if (folder != null)
 | 
			
		||||
                {
 | 
			
		||||
                    await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
 | 
			
		||||
                    await logger.LogInformation("Folder Saved {Folder}", folder);
 | 
			
		||||
                    NavigationManager.NavigateTo(NavigateUrl());
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ using System.Net;
 | 
			
		||||
using Oqtane.Enums;
 | 
			
		||||
using Oqtane.Infrastructure;
 | 
			
		||||
using Oqtane.Repository;
 | 
			
		||||
using Microsoft.AspNetCore.Routing.Constraints;
 | 
			
		||||
 | 
			
		||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
 | 
			
		||||
 | 
			
		||||
@ -396,12 +397,13 @@ namespace Oqtane.Controllers
 | 
			
		||||
        [HttpGet("download/{id}")]
 | 
			
		||||
        public IActionResult Download(int id)
 | 
			
		||||
        {
 | 
			
		||||
            string errorpath = Path.Combine(GetFolderPath("images"), "error.png");
 | 
			
		||||
            Models.File file = _files.GetFile(id);
 | 
			
		||||
            if (file != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
 | 
			
		||||
                {
 | 
			
		||||
                    string filepath = Path.Combine(GetFolderPath(file.Folder) , file.Name);
 | 
			
		||||
                    string filepath = Path.Combine(GetFolderPath(file.Folder), file.Name);
 | 
			
		||||
                    if (System.IO.File.Exists(filepath))
 | 
			
		||||
                    {
 | 
			
		||||
                        byte[] filebytes = System.IO.File.ReadAllBytes(filepath);
 | 
			
		||||
@ -411,21 +413,24 @@ namespace Oqtane.Controllers
 | 
			
		||||
                    {
 | 
			
		||||
                        _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
 | 
			
		||||
                        HttpContext.Response.StatusCode = 404;
 | 
			
		||||
                        return null;
 | 
			
		||||
                        byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
 | 
			
		||||
                        return File(filebytes, "application/octet-stream", file.Name);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id);
 | 
			
		||||
                    HttpContext.Response.StatusCode = 401;
 | 
			
		||||
                    return null;
 | 
			
		||||
                    byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
 | 
			
		||||
                    return File(filebytes, "application/octet-stream", file.Name);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
 | 
			
		||||
                HttpContext.Response.StatusCode = 404;
 | 
			
		||||
                return null;
 | 
			
		||||
                byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
 | 
			
		||||
                return File(filebytes, "application/octet-stream", "error.png");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,6 @@ using Oqtane.Extensions;
 | 
			
		||||
using Oqtane.Infrastructure;
 | 
			
		||||
using Oqtane.Repository;
 | 
			
		||||
using Oqtane.Security;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Controllers
 | 
			
		||||
{
 | 
			
		||||
@ -106,13 +105,23 @@ namespace Oqtane.Controllers
 | 
			
		||||
                }
 | 
			
		||||
                if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
 | 
			
		||||
                {
 | 
			
		||||
                    if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
 | 
			
		||||
                    if (FolderPathValid(folder))
 | 
			
		||||
                    {
 | 
			
		||||
                        Folder parent = _folders.GetFolder(folder.ParentId.Value);
 | 
			
		||||
                        folder.Path = Utilities.PathCombine(parent.Path, folder.Name,"\\");
 | 
			
		||||
                        if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            Folder parent = _folders.GetFolder(folder.ParentId.Value);
 | 
			
		||||
                            folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
 | 
			
		||||
                        }
 | 
			
		||||
                        folder.Path = Utilities.PathCombine(folder.Path, "\\");
 | 
			
		||||
                        folder = _folders.AddFolder(folder);
 | 
			
		||||
                        _logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        _logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
 | 
			
		||||
                        HttpContext.Response.StatusCode = 401;
 | 
			
		||||
                        folder = null;
 | 
			
		||||
                    }
 | 
			
		||||
                    folder = _folders.AddFolder(folder);
 | 
			
		||||
                    _logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
@ -131,13 +140,23 @@ namespace Oqtane.Controllers
 | 
			
		||||
        {
 | 
			
		||||
            if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
 | 
			
		||||
            {
 | 
			
		||||
                if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
 | 
			
		||||
                if (FolderPathValid(folder))
 | 
			
		||||
                {
 | 
			
		||||
                    Folder parent = _folders.GetFolder(folder.ParentId.Value);
 | 
			
		||||
                    folder.Path = Utilities.PathCombine(parent.Path, folder.Name,"\\");
 | 
			
		||||
                    if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        Folder parent = _folders.GetFolder(folder.ParentId.Value);
 | 
			
		||||
                        folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
 | 
			
		||||
                    }
 | 
			
		||||
                    folder.Path = Utilities.PathCombine(folder.Path, "\\");
 | 
			
		||||
                    folder = _folders.UpdateFolder(folder);
 | 
			
		||||
                    _logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
 | 
			
		||||
                    HttpContext.Response.StatusCode = 401;
 | 
			
		||||
                    folder = null;
 | 
			
		||||
                }
 | 
			
		||||
                folder = _folders.UpdateFolder(folder);
 | 
			
		||||
                _logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@ -191,5 +210,11 @@ namespace Oqtane.Controllers
 | 
			
		||||
                HttpContext.Response.StatusCode = 401;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool FolderPathValid(Folder folder)
 | 
			
		||||
        {
 | 
			
		||||
            // prevent folder path traversal and reserved devices
 | 
			
		||||
            return (!folder.Name.Contains("\\") && !folder.Name.Contains("/") && !Constants.ReservedDevices.Split(',').Contains(folder.Name.ToUpper()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Oqtane.Models;
 | 
			
		||||
using Oqtane.Repository;
 | 
			
		||||
using Oqtane.Shared;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Controllers
 | 
			
		||||
{
 | 
			
		||||
@ -17,6 +19,7 @@ namespace Oqtane.Controllers
 | 
			
		||||
 | 
			
		||||
        // GET: api/<controller>
 | 
			
		||||
        [HttpGet]
 | 
			
		||||
        [Authorize(Roles = Constants.HostRole)]
 | 
			
		||||
        public IEnumerable<SiteTemplate> Get()
 | 
			
		||||
        {
 | 
			
		||||
            return _siteTemplates.GetSiteTemplates();
 | 
			
		||||
 | 
			
		||||
@ -101,6 +101,12 @@
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .app-logo {
 | 
			
		||||
        display: block;
 | 
			
		||||
        margin-left: auto;
 | 
			
		||||
        margin-right: auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .breadcrumbs {
 | 
			
		||||
        position: fixed;
 | 
			
		||||
        left: 275px;
 | 
			
		||||
@ -163,7 +169,13 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 767px) {    
 | 
			
		||||
@media (max-width: 767px) {
 | 
			
		||||
    .app-logo {
 | 
			
		||||
        height: 80px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .breadcrumbs {
 | 
			
		||||
        position: fixed;
 | 
			
		||||
        top: 150px;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Oqtane.Server/wwwroot/images/error.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Oqtane.Server/wwwroot/images/error.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.6 KiB  | 
@ -81,14 +81,26 @@ window.interop = {
 | 
			
		||||
            if (link.href !== url) {
 | 
			
		||||
                link.setAttribute('href', url);
 | 
			
		||||
            }
 | 
			
		||||
            if (type !== "" && link.type !== type) {
 | 
			
		||||
                link.setAttribute('type', type);
 | 
			
		||||
            if (type !== "") {
 | 
			
		||||
                if (link.type !== type) {
 | 
			
		||||
                    link.setAttribute('type', type);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                link.removeAttribute('type');
 | 
			
		||||
            }
 | 
			
		||||
            if (integrity !== "" && link.integrity !== integrity) {
 | 
			
		||||
                link.setAttribute('integrity', integrity);
 | 
			
		||||
            if (integrity !== "") {
 | 
			
		||||
                if (link.integrity !== integrity) {
 | 
			
		||||
                    link.setAttribute('integrity', integrity);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                link.removeAttribute('integrity');
 | 
			
		||||
            }
 | 
			
		||||
            if (crossorigin !== "" && link.crossOrigin !== crossorigin) {
 | 
			
		||||
                link.setAttribute('crossorigin', crossorigin);
 | 
			
		||||
            if (crossorigin !== "") {
 | 
			
		||||
                if (link.crossOrigin !== crossorigin) {
 | 
			
		||||
                    link.setAttribute('crossorigin', crossorigin);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                link.removeAttribute('crossorigin');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@ -126,11 +138,19 @@ window.interop = {
 | 
			
		||||
                if (script.src !== src) {
 | 
			
		||||
                    script.src = src;
 | 
			
		||||
                }
 | 
			
		||||
                if (integrity !== "" && script.integrity !== integrity) {
 | 
			
		||||
                    script.setAttribute('integrity', integrity);
 | 
			
		||||
                if (integrity !== "") {
 | 
			
		||||
                    if (script.integrity !== integrity) {
 | 
			
		||||
                        script.setAttribute('integrity', integrity);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    script.removeAttribute('integrity');
 | 
			
		||||
                }
 | 
			
		||||
                if (crossorigin !== "" && script.crossorigin !== crossorigin) {
 | 
			
		||||
                    script.setAttribute('crossorigin', crossorigin);
 | 
			
		||||
                if (crossorigin !== "") {
 | 
			
		||||
                    if (script.crossOrigin !== crossorigin) {
 | 
			
		||||
                        script.setAttribute('crossorigin', crossorigin);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    script.removeAttribute('crossorigin');
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
 | 
			
		||||
@ -43,5 +43,6 @@
 | 
			
		||||
 | 
			
		||||
        public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png";
 | 
			
		||||
        public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
 | 
			
		||||
        public const string ReservedDevices = "CON,NUL,PRN,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user