templates support
This commit is contained in:
91
Inspectron.Epson.Templates/Storage/FileTemplateStorage.cs
Normal file
91
Inspectron.Epson.Templates/Storage/FileTemplateStorage.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user