71 lines
2.5 KiB
C#
71 lines
2.5 KiB
C#
namespace dy.net.storage
|
|
{
|
|
public static class SafeLocalMigrationFile
|
|
{
|
|
public static bool TryResolve(string path, IEnumerable<string> allowedRoots, out string fullPath, out string error)
|
|
{
|
|
fullPath = null;
|
|
error = null;
|
|
if (string.IsNullOrWhiteSpace(path))
|
|
{
|
|
error = "本地路径为空";
|
|
return false;
|
|
}
|
|
|
|
try { fullPath = Path.GetFullPath(path); }
|
|
catch (Exception ex)
|
|
{
|
|
error = "本地路径无效:" + ex.Message;
|
|
return false;
|
|
}
|
|
|
|
var resolvedPath = fullPath;
|
|
var root = (allowedRoots ?? Array.Empty<string>())
|
|
.Select(Path.GetFullPath)
|
|
.Where(candidate => IsWithin(resolvedPath, candidate))
|
|
.OrderByDescending(x => x.Length)
|
|
.FirstOrDefault();
|
|
if (root == null)
|
|
{
|
|
error = "文件不在账号配置的旧存储根目录内";
|
|
return false;
|
|
}
|
|
|
|
if (!File.Exists(fullPath))
|
|
{
|
|
error = "本地文件不存在";
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
for (var current = fullPath; !string.IsNullOrWhiteSpace(current); current = Path.GetDirectoryName(current))
|
|
{
|
|
FileSystemInfo info = File.Exists(current) ? new FileInfo(current) : new DirectoryInfo(current);
|
|
if (!string.IsNullOrWhiteSpace(info.LinkTarget))
|
|
{
|
|
error = "旧文件路径包含符号链接,已拒绝迁移";
|
|
return false;
|
|
}
|
|
if (string.Equals(current, root, StringComparison.Ordinal)) break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
error = "无法验证旧文件路径:" + ex.Message;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool IsWithin(string candidate, string root)
|
|
{
|
|
var fullCandidate = Path.GetFullPath(candidate).TrimEnd(Path.DirectorySeparatorChar);
|
|
var fullRoot = Path.GetFullPath(root).TrimEnd(Path.DirectorySeparatorChar);
|
|
return string.Equals(fullCandidate, fullRoot, StringComparison.Ordinal)
|
|
|| fullCandidate.StartsWith(fullRoot + Path.DirectorySeparatorChar, StringComparison.Ordinal);
|
|
}
|
|
}
|
|
}
|