Classify NTFS paths via DFS metadata
This commit is contained in:
@@ -47,6 +47,7 @@ namespace C4IT.LIAM
|
||||
public eNtfsPathKind Kind { get; set; } = eNtfsPathKind.Unknown;
|
||||
public string BoundaryPath { get; set; } = string.Empty;
|
||||
public string ParentBoundaryPath { get; set; } = string.Empty;
|
||||
public string ParentPath { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public int Level { get; set; } = -1;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ namespace C4IT.LIAM
|
||||
public readonly cNtfsBase ntfsBase = new cNtfsBase();
|
||||
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
||||
private readonly Dictionary<string, HashSet<string>> publishedShareCache = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Dictionary<string, string> dfsEntryPathCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
//public readonly bool WithoutPrivateFolders = true;
|
||||
|
||||
@@ -274,7 +276,10 @@ namespace C4IT.LIAM
|
||||
? new DirectoryInfo(classification.NormalizedPath).CreationTimeUtc.ToString("s")
|
||||
: DateTime.MinValue.ToString("s")
|
||||
};
|
||||
var folder = new cLiamNtfsFolder(this, null, null, folderData, classification.ParentBoundaryPath);
|
||||
var parentPath = !string.IsNullOrWhiteSpace(classification.ParentPath)
|
||||
? classification.ParentPath
|
||||
: classification.ParentBoundaryPath;
|
||||
var folder = new cLiamNtfsFolder(this, null, null, folderData, parentPath);
|
||||
await folder.ResolvePermissionGroupsAsync(folder.TechnicalName);
|
||||
return folder;
|
||||
}
|
||||
@@ -303,59 +308,128 @@ namespace C4IT.LIAM
|
||||
if (segments.Length < 2)
|
||||
return classification;
|
||||
|
||||
var serverName = segments[0];
|
||||
var publishedShares = GetPublishedShareNames(serverName);
|
||||
var firstBoundaryPath = BuildUncPath(segments, 2);
|
||||
classification.ParentPath = segments.Length > 2
|
||||
? BuildUncPath(segments, segments.Length - 1)
|
||||
: string.Empty;
|
||||
|
||||
if (segments.Length == 2)
|
||||
var dfsPrefixes = GetDfsObjectPrefixes(normalizedPath);
|
||||
if (dfsPrefixes.Count > 0)
|
||||
{
|
||||
if (publishedShares.Contains(segments[1]))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.ClassicShare;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
return classification;
|
||||
}
|
||||
var namespaceRootPath = dfsPrefixes[0];
|
||||
var deepestDfsPath = dfsPrefixes[dfsPrefixes.Count - 1];
|
||||
|
||||
if (Directory.Exists(normalizedPath))
|
||||
if (PathsEqual(normalizedPath, namespaceRootPath))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.DfsNamespaceRoot;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (publishedShares.Contains(segments[1]))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.BoundaryPath = firstBoundaryPath;
|
||||
classification.ParentBoundaryPath = segments.Length == 3
|
||||
? firstBoundaryPath
|
||||
: BuildUncPath(segments, segments.Length - 1);
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (Directory.Exists(firstBoundaryPath))
|
||||
{
|
||||
if (segments.Length == 3)
|
||||
if (PathsEqual(normalizedPath, deepestDfsPath))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.DfsLink;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
classification.ParentBoundaryPath = firstBoundaryPath;
|
||||
classification.BoundaryPath = deepestDfsPath;
|
||||
classification.ParentBoundaryPath = dfsPrefixes.Count > 1
|
||||
? dfsPrefixes[dfsPrefixes.Count - 2]
|
||||
: namespaceRootPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.BoundaryPath = BuildUncPath(segments, 3);
|
||||
classification.ParentBoundaryPath = segments.Length == 4
|
||||
? BuildUncPath(segments, 3)
|
||||
: BuildUncPath(segments, segments.Length - 1);
|
||||
classification.BoundaryPath = deepestDfsPath;
|
||||
classification.ParentBoundaryPath = classification.ParentPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
var shareBoundaryPath = GetPublishedShareBoundaryPath(segments);
|
||||
if (!string.IsNullOrWhiteSpace(shareBoundaryPath))
|
||||
{
|
||||
if (PathsEqual(normalizedPath, shareBoundaryPath))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.ClassicShare;
|
||||
classification.BoundaryPath = shareBoundaryPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.BoundaryPath = shareBoundaryPath;
|
||||
classification.ParentBoundaryPath = classification.ParentPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (Directory.Exists(normalizedPath))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.ParentBoundaryPath = classification.ParentPath;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
private List<string> GetDfsObjectPrefixes(string path)
|
||||
{
|
||||
var normalizedPath = NormalizeUncPath(path);
|
||||
var segments = GetUncSegments(normalizedPath);
|
||||
var prefixes = new List<string>();
|
||||
|
||||
for (var segmentCount = 2; segmentCount <= segments.Length; segmentCount++)
|
||||
{
|
||||
var prefix = BuildUncPath(segments, segmentCount);
|
||||
string entryPath;
|
||||
if (!TryGetDfsEntryPath(prefix, out entryPath))
|
||||
continue;
|
||||
|
||||
prefixes.Add(!string.IsNullOrWhiteSpace(entryPath)
|
||||
? NormalizeUncPath(entryPath)
|
||||
: prefix);
|
||||
}
|
||||
|
||||
return prefixes
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(i => GetUncSegments(i).Length)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private bool TryGetDfsEntryPath(string path, out string entryPath)
|
||||
{
|
||||
var normalizedPath = NormalizeUncPath(path);
|
||||
if (dfsEntryPathCache.TryGetValue(normalizedPath, out entryPath))
|
||||
return !string.IsNullOrWhiteSpace(entryPath);
|
||||
|
||||
string resolvedEntryPath;
|
||||
if (cNetworkConnection.TryGetDfsEntryPath(normalizedPath, out resolvedEntryPath))
|
||||
{
|
||||
entryPath = NormalizeUncPath(string.IsNullOrWhiteSpace(resolvedEntryPath) ? normalizedPath : resolvedEntryPath);
|
||||
dfsEntryPathCache[normalizedPath] = entryPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
dfsEntryPathCache[normalizedPath] = string.Empty;
|
||||
entryPath = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetPublishedShareBoundaryPath(string[] segments)
|
||||
{
|
||||
if (segments == null || segments.Length < 2)
|
||||
return string.Empty;
|
||||
|
||||
var serverName = segments[0];
|
||||
var publishedShares = GetPublishedShareNames(serverName);
|
||||
if (!publishedShares.Contains(segments[1]))
|
||||
return string.Empty;
|
||||
|
||||
return BuildUncPath(segments, 2);
|
||||
}
|
||||
|
||||
private bool PathsEqual(string left, string right)
|
||||
{
|
||||
return string.Equals(
|
||||
NormalizeUncPath(left),
|
||||
NormalizeUncPath(right),
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private string NormalizeUncPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
|
||||
Reference in New Issue
Block a user