113 lines
3.8 KiB
C#
113 lines
3.8 KiB
C#
using System.Text;
|
|
using ICSharpCode.SharpZipLib.GZip;
|
|
using ICSharpCode.SharpZipLib.Tar;
|
|
using ICSharpCode.SharpZipLib.Zip;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Moonlight.ApiServer.Helpers;
|
|
using Moonlight.Shared.Http.Requests.Admin.Sys.Files;
|
|
|
|
namespace Moonlight.ApiServer.Http.Controllers.Admin.Sys.Files;
|
|
|
|
[ApiController]
|
|
[Route("api/admin/system/files")]
|
|
[Authorize(Policy = "permissions:admin.system.files")]
|
|
public class DecompressController : Controller
|
|
{
|
|
private const string BaseDirectory = "storage";
|
|
|
|
[HttpPost("decompress")]
|
|
public async Task DecompressAsync([FromBody] DecompressRequest request)
|
|
{
|
|
var path = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Path));
|
|
var destination = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Destination));
|
|
|
|
switch (request.Format)
|
|
{
|
|
case "tar.gz":
|
|
await DecompressTarGzAsync(path, destination);
|
|
break;
|
|
|
|
case "zip":
|
|
await DecompressZipAsync(path, destination);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#region Tar Gz
|
|
|
|
private async Task DecompressTarGzAsync(string path, string destination)
|
|
{
|
|
await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
await using var gzipInputStream = new GZipInputStream(fs);
|
|
await using var tarInputStream = new TarInputStream(gzipInputStream, Encoding.UTF8);
|
|
|
|
while (true)
|
|
{
|
|
var entry = await tarInputStream.GetNextEntryAsync(CancellationToken.None);
|
|
|
|
if (entry == null)
|
|
break;
|
|
|
|
var safeFilePath = FilePathHelper.SanitizePath(entry.Name);
|
|
var fileDestination = Path.Combine(destination, safeFilePath);
|
|
var parentFolder = Path.GetDirectoryName(fileDestination);
|
|
|
|
// Ensure parent directory exists, if it's not the base directory
|
|
if (parentFolder != null && parentFolder != BaseDirectory)
|
|
Directory.CreateDirectory(parentFolder);
|
|
|
|
await using var fileDestinationFs =
|
|
System.IO.File.Open(fileDestination, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
|
await tarInputStream.CopyToAsync(fileDestinationFs, CancellationToken.None);
|
|
|
|
await fileDestinationFs.FlushAsync();
|
|
fileDestinationFs.Close();
|
|
}
|
|
|
|
tarInputStream.Close();
|
|
gzipInputStream.Close();
|
|
fs.Close();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Zip
|
|
|
|
private async Task DecompressZipAsync(string path, string destination)
|
|
{
|
|
await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
await using var zipInputStream = new ZipInputStream(fs);
|
|
|
|
while (true)
|
|
{
|
|
var entry = zipInputStream.GetNextEntry();
|
|
|
|
if (entry == null)
|
|
break;
|
|
|
|
if (entry.IsDirectory)
|
|
continue;
|
|
|
|
var safeFilePath = FilePathHelper.SanitizePath(entry.Name);
|
|
var fileDestination = Path.Combine(destination, safeFilePath);
|
|
var parentFolder = Path.GetDirectoryName(fileDestination);
|
|
|
|
// Ensure parent directory exists, if it's not the base directory
|
|
if (parentFolder != null && parentFolder != BaseDirectory)
|
|
Directory.CreateDirectory(parentFolder);
|
|
|
|
await using var fileDestinationFs =
|
|
System.IO.File.Open(fileDestination, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
|
await zipInputStream.CopyToAsync(fileDestinationFs, CancellationToken.None);
|
|
|
|
await fileDestinationFs.FlushAsync();
|
|
fileDestinationFs.Close();
|
|
}
|
|
|
|
zipInputStream.Close();
|
|
fs.Close();
|
|
}
|
|
|
|
#endregion
|
|
} |