Merge pull request #5314 from sbwalker/dev

improve filename validation in module content export
This commit is contained in:
Shaun Walker 2025-05-16 08:26:04 -04:00 committed by GitHub
commit 68edbbbdb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 17 additions and 17 deletions

View File

@ -50,6 +50,11 @@
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Export Content"; public override string Title => "Export Content";
protected override void OnInitialized()
{
_filename = Utilities.GetFriendlyUrl(ModuleState.Title);
}
private async Task ExportText() private async Task ExportText()
{ {
try try
@ -71,8 +76,8 @@
var folderid = _filemanager.GetFolderId(); var folderid = _filemanager.GetFolderId();
if (folderid != -1 && !string.IsNullOrEmpty(_filename)) if (folderid != -1 && !string.IsNullOrEmpty(_filename))
{ {
var result = await ModuleService.ExportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId, folderid, _filename); var fileid = await ModuleService.ExportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId, folderid, _filename);
if (result.Success) if (fileid != -1)
{ {
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success); AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
} }

View File

@ -67,7 +67,7 @@ namespace Oqtane.Services
/// <param name="pageId"></param> /// <param name="pageId"></param>
/// <param name="folderId"></param> /// <param name="folderId"></param>
/// <param name="filename"></param> /// <param name="filename"></param>
/// <returns>success/failure</returns> /// <returns>file id</returns>
Task<Result> ExportModuleAsync(int moduleId, int pageId, int folderId, string filename); Task<int> ExportModuleAsync(int moduleId, int pageId, int folderId, string filename);
} }
} }

View File

@ -51,9 +51,9 @@ namespace Oqtane.Services
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}"); return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}");
} }
public async Task<Result> ExportModuleAsync(int moduleId, int pageId, int folderId, string filename) public async Task<int> ExportModuleAsync(int moduleId, int pageId, int folderId, string filename)
{ {
return await PostJsonAsync<Result>($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}&folderid={folderId}&filename={filename}", null); return await PostJsonAsync<string,int>($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}&folderid={folderId}&filename={filename}", null);
} }
} }
} }

View File

@ -22,7 +22,6 @@ 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;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
// ReSharper disable StringIndexOfIsCultureSpecific.1 // ReSharper disable StringIndexOfIsCultureSpecific.1

View File

@ -10,9 +10,6 @@ using Oqtane.Repository;
using Oqtane.Security; using Oqtane.Security;
using System.Net; using System.Net;
using System.IO; using System.IO;
using System;
using static System.Net.WebRequestMethods;
using System.Net.Http;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
@ -259,9 +256,9 @@ namespace Oqtane.Controllers
// POST api/<controller>/export?moduleid=x&pageid=y&folderid=z&filename=a // POST api/<controller>/export?moduleid=x&pageid=y&folderid=z&filename=a
[HttpPost("export")] [HttpPost("export")]
[Authorize(Roles = RoleNames.Registered)] [Authorize(Roles = RoleNames.Registered)]
public Result Export(int moduleid, int pageid, int folderid, string filename) public int Export(int moduleid, int pageid, int folderid, string filename)
{ {
var result = new Result(false); var fileid = -1;
var module = _modules.GetModule(moduleid); var module = _modules.GetModule(moduleid);
if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, module.SiteId, EntityNames.Page, pageid, PermissionNames.Edit) && if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, module.SiteId, EntityNames.Page, pageid, PermissionNames.Edit) &&
_userPermissions.IsAuthorized(User, module.SiteId, EntityNames.Folder, folderid, PermissionNames.Edit) && !string.IsNullOrEmpty(filename)) _userPermissions.IsAuthorized(User, module.SiteId, EntityNames.Folder, folderid, PermissionNames.Edit) && !string.IsNullOrEmpty(filename))
@ -278,7 +275,7 @@ namespace Oqtane.Controllers
} }
// create json file // create json file
filename = Path.GetFileNameWithoutExtension(filename) + ".json"; filename = Utilities.GetFriendlyUrl(Path.GetFileNameWithoutExtension(filename)) + ".json";
string filepath = Path.Combine(folderPath, filename); string filepath = Path.Combine(folderPath, filename);
if (System.IO.File.Exists(filepath)) if (System.IO.File.Exists(filepath))
{ {
@ -298,9 +295,7 @@ namespace Oqtane.Controllers
file.Size = (int)new FileInfo(filepath).Length; file.Size = (int)new FileInfo(filepath).Length;
_files.UpdateFile(file); _files.UpdateFile(file);
} }
fileid = file.FileId;
result.Success = true;
result.Message = filename;
_logger.Log(LogLevel.Information, this, LogFunction.Read, "Content Exported For Module {ModuleId} To Folder {FolderId}", moduleid, folderid); _logger.Log(LogLevel.Information, this, LogFunction.Read, "Content Exported For Module {ModuleId} To Folder {FolderId}", moduleid, folderid);
} }
@ -309,7 +304,8 @@ namespace Oqtane.Controllers
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Export Attempt For Module {Module} To Folder {FolderId}", moduleid, folderid); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Export Attempt For Module {Module} To Folder {FolderId}", moduleid, folderid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
} }
return result;
return fileid;
} }
// POST api/<controller>/import?moduleid=x&pageid=y // POST api/<controller>/import?moduleid=x&pageid=y