improve file upload validation and error handling on server
This commit is contained in:
parent
dec0c0649c
commit
8c83a18f93
|
@ -22,6 +22,7 @@ using Microsoft.AspNetCore.Cors;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
|
@ -430,80 +431,96 @@ namespace Oqtane.Controllers
|
||||||
[HttpPost("upload")]
|
[HttpPost("upload")]
|
||||||
public async Task<IActionResult> UploadFile([FromForm] string folder, IFormFile formfile)
|
public async Task<IActionResult> UploadFile([FromForm] string folder, IFormFile formfile)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(folder))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Upload Does Not Contain A Folder");
|
||||||
|
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
if (formfile == null || formfile.Length <= 0)
|
if (formfile == null || formfile.Length <= 0)
|
||||||
{
|
{
|
||||||
return NoContent();
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Upload Does Not Contain A File");
|
||||||
|
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure filename is valid
|
// ensure filename is valid
|
||||||
if (!formfile.FileName.IsPathOrFileValid() || !HasValidFileExtension(formfile.FileName))
|
if (!formfile.FileName.IsPathOrFileValid() || !HasValidFileExtension(formfile.FileName))
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", formfile.FileName);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Upload File Name Is Invalid Or Contains Invalid Extension {File}", formfile.FileName);
|
||||||
return NoContent();
|
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure headers exist
|
// ensure headers exist
|
||||||
if (!Request.Headers.TryGetValue("PartCount", out StringValues partCount) || !Request.Headers.TryGetValue("TotalParts", out StringValues totalParts))
|
if (!Request.Headers.TryGetValue("PartCount", out StringValues partcount) || !int.TryParse(partcount, out int partCount) || partCount <= 0 ||
|
||||||
|
!Request.Headers.TryGetValue("TotalParts", out StringValues totalparts) || !int.TryParse(totalparts, out int totalParts) || totalParts <= 0)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Upload Request Is Missing Required Headers");
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Upload Is Missing Required Headers");
|
||||||
return NoContent();
|
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
string fileName = formfile.FileName + ".part_" + int.Parse(partCount).ToString("000") + "_" + int.Parse(totalParts).ToString("000");
|
// create file name using header values
|
||||||
|
string fileName = formfile.FileName + ".part_" + partCount.ToString("000") + "_" + totalParts.ToString("000");
|
||||||
string folderPath = "";
|
string folderPath = "";
|
||||||
|
|
||||||
int FolderId;
|
try
|
||||||
if (int.TryParse(folder, out FolderId))
|
|
||||||
{
|
{
|
||||||
Folder Folder = _folders.GetFolder(FolderId);
|
int FolderId;
|
||||||
if (Folder != null && Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, Folder.PermissionList))
|
if (int.TryParse(folder, out FolderId))
|
||||||
{
|
{
|
||||||
folderPath = _folders.GetFolderPath(Folder);
|
Folder Folder = _folders.GetFolder(FolderId);
|
||||||
}
|
if (Folder != null && Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, Folder.PermissionList))
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FolderId = -1;
|
|
||||||
if (User.IsInRole(RoleNames.Host))
|
|
||||||
{
|
|
||||||
folderPath = GetFolderPath(folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(folderPath))
|
|
||||||
{
|
|
||||||
CreateDirectory(folderPath);
|
|
||||||
using (var stream = new FileStream(Path.Combine(folderPath, fileName), FileMode.Create))
|
|
||||||
{
|
|
||||||
await formfile.CopyToAsync(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
string upload = await MergeFile(folderPath, fileName);
|
|
||||||
if (upload != "" && FolderId != -1)
|
|
||||||
{
|
|
||||||
var file = CreateFile(upload, FolderId, Path.Combine(folderPath, upload));
|
|
||||||
if (file != null)
|
|
||||||
{
|
{
|
||||||
if (file.FileId == 0)
|
folderPath = _folders.GetFolderPath(Folder);
|
||||||
{
|
}
|
||||||
file = _files.AddFile(file);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
FolderId = -1;
|
||||||
file = _files.UpdateFile(file);
|
if (User.IsInRole(RoleNames.Host))
|
||||||
}
|
{
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folderPath, upload));
|
folderPath = GetFolderPath(folder);
|
||||||
_syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Upload Attempt {Folder} {File}", folder, formfile.FileName);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NoContent();
|
if (!string.IsNullOrEmpty(folderPath))
|
||||||
|
{
|
||||||
|
CreateDirectory(folderPath);
|
||||||
|
using (var stream = new FileStream(Path.Combine(folderPath, fileName), FileMode.Create))
|
||||||
|
{
|
||||||
|
await formfile.CopyToAsync(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
string upload = await MergeFile(folderPath, fileName);
|
||||||
|
if (upload != "" && FolderId != -1)
|
||||||
|
{
|
||||||
|
var file = CreateFile(upload, FolderId, Path.Combine(folderPath, upload));
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
if (file.FileId == 0)
|
||||||
|
{
|
||||||
|
file = _files.AddFile(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file = _files.UpdateFile(file);
|
||||||
|
}
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folderPath, upload));
|
||||||
|
_syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Upload Attempt {Folder} {File}", folder, formfile.FileName);
|
||||||
|
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "File Upload Attempt Failed {Folder} {File}", folder, formfile.FileName);
|
||||||
|
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MergeFile(string folder, string filename)
|
private async Task<string> MergeFile(string folder, string filename)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user