Files
Print_server/Inspectron.Epson.Templates/Storage/FileTemplateStorage.cs
2026-01-21 15:56:37 +01:00

92 lines
2.5 KiB
C#

using System.Collections.Concurrent;
namespace Inspectron.Epson.Templates.Storage;
public class FileTemplateStorage : ITemplateStorage
{
private readonly string _basePath;
private readonly string _templateExtension;
private readonly ConcurrentDictionary<string, string> _cache = new();
public FileTemplateStorage(string basePath, string templateExtension = ".template")
{
_basePath = Path.GetFullPath(basePath);
_templateExtension = templateExtension;
if (!Directory.Exists(_basePath))
{
Directory.CreateDirectory(_basePath);
}
}
public string? Load(string templatePath)
{
var normalizedPath = NormalizePath(templatePath);
if (_cache.TryGetValue(normalizedPath, out var cached))
{
return cached;
}
var fullPath = GetFullPath(normalizedPath);
if (!File.Exists(fullPath))
{
return null;
}
var content = File.ReadAllText(fullPath);
_cache[normalizedPath] = content;
return content;
}
public bool Exists(string templatePath)
{
var normalizedPath = NormalizePath(templatePath);
var fullPath = GetFullPath(normalizedPath);
return File.Exists(fullPath);
}
public void Reload()
{
_cache.Clear();
}
public IEnumerable<string> ListTemplates()
{
if (!Directory.Exists(_basePath))
{
yield break;
}
var files = Directory.GetFiles(_basePath, $"*{_templateExtension}", SearchOption.AllDirectories);
foreach (var file in files)
{
var relativePath = Path.GetRelativePath(_basePath, file);
yield return relativePath.Replace('\\', '/');
}
}
private string NormalizePath(string path)
{
// Ensure the path has the correct extension
if (!path.EndsWith(_templateExtension, StringComparison.OrdinalIgnoreCase))
{
path += _templateExtension;
}
// Normalize path separators
return path.Replace('\\', '/');
}
private string GetFullPath(string normalizedPath)
{
// Security: prevent directory traversal
var fullPath = Path.GetFullPath(Path.Combine(_basePath, normalizedPath));
if (!fullPath.StartsWith(_basePath, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException($"Invalid template path: {normalizedPath}");
}
return fullPath;
}
}