From 9cfd2662943ebcf095f181abffea073613905abf Mon Sep 17 00:00:00 2001 From: Meik Date: Fri, 13 Mar 2026 20:20:16 +0100 Subject: [PATCH] Support NTFS server roots --- LiamBaseClasses/C4IT.LIAM.Base.cs | 1 + LiamNtfs/C4IT.LIAM.Ntfs.cs | 114 ++++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 15 deletions(-) diff --git a/LiamBaseClasses/C4IT.LIAM.Base.cs b/LiamBaseClasses/C4IT.LIAM.Base.cs index 2af7118..d377fe6 100644 --- a/LiamBaseClasses/C4IT.LIAM.Base.cs +++ b/LiamBaseClasses/C4IT.LIAM.Base.cs @@ -30,6 +30,7 @@ namespace C4IT.LIAM public enum eLiamDataAreaTypes { Unknown = 0, + NtfsServerRoot = 100, NtfsShare = 101, NtfsFolder = 102, DfsNamespaceRoot = 103, diff --git a/LiamNtfs/C4IT.LIAM.Ntfs.cs b/LiamNtfs/C4IT.LIAM.Ntfs.cs index d7bba16..5dbdb80 100644 --- a/LiamNtfs/C4IT.LIAM.Ntfs.cs +++ b/LiamNtfs/C4IT.LIAM.Ntfs.cs @@ -179,20 +179,7 @@ namespace C4IT.LIAM if (Depth == 0) return DataAreas; - var DAL = await ntfsBase.RequestFoldersListAsync(this.RootPath, Depth); - if (DAL == null) - return null; - - foreach (var Entry in DAL) - { - if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Value.DisplayName, this.DataAreaRegEx).Success) - continue; - - var classification = ClassifyPath(Entry.Value.Path); - var dataArea = await BuildDataAreaAsync(classification, Entry.Value as cNtfsResultFolder); - if (dataArea != null) - DataAreas.Add(dataArea); - } + DataAreas.AddRange(await GetChildDataAreasAsync(rootClassification, Depth)); return DataAreas; } catch (Exception E) @@ -242,6 +229,10 @@ namespace C4IT.LIAM switch (classification.Kind) { + case eNtfsPathKind.ServerRoot: + { + return new cLiamNtfsServerRoot(this, classification.NormalizedPath, classification.Level); + } case eNtfsPathKind.ClassicShare: case eNtfsPathKind.DfsLink: { @@ -366,6 +357,74 @@ namespace C4IT.LIAM return classification; } + private async Task> GetChildDataAreasAsync(cNtfsPathClassification parentClassification, int depth) + { + var children = new List(); + if (parentClassification == null || depth == 0) + return children; + + if (parentClassification.Kind == eNtfsPathKind.ServerRoot) + { + foreach (var childPath in GetServerRootChildPaths(parentClassification.NormalizedPath)) + { + var childClassification = ClassifyPath(childPath); + if (!ShouldIncludeDataArea(childClassification.DisplayName)) + continue; + + var childDataArea = await BuildDataAreaAsync(childClassification); + if (childDataArea == null) + continue; + + children.Add(childDataArea); + if (depth > 1) + children.AddRange(await GetChildDataAreasAsync(childClassification, depth - 1)); + } + + return children; + } + + var folderEntries = await ntfsBase.RequestFoldersListAsync(parentClassification.NormalizedPath, 1); + if (folderEntries == null) + return children; + + foreach (var entry in folderEntries.Values.OfType()) + { + var childClassification = ClassifyPath(entry.Path); + if (!ShouldIncludeDataArea(childClassification.DisplayName)) + continue; + + var childDataArea = await BuildDataAreaAsync(childClassification, entry); + if (childDataArea == null) + continue; + + children.Add(childDataArea); + if (depth > 1) + children.AddRange(await GetChildDataAreasAsync(childClassification, depth - 1)); + } + + return children; + } + + private IEnumerable GetServerRootChildPaths(string serverRootPath) + { + var segments = GetUncSegments(serverRootPath); + if (segments.Length != 1) + return Enumerable.Empty(); + + var serverName = segments[0]; + return GetPublishedShareNames(serverName) + .OrderBy(i => i, StringComparer.OrdinalIgnoreCase) + .Select(shareName => BuildUncPath(new[] { serverName, shareName }, 2)); + } + + private bool ShouldIncludeDataArea(string displayName) + { + if (string.IsNullOrEmpty(this.DataAreaRegEx)) + return true; + + return Regex.Match(displayName ?? string.Empty, this.DataAreaRegEx).Success; + } + private List GetDfsObjectPrefixes(string path) { var normalizedPath = NormalizeUncPath(path); @@ -757,7 +816,12 @@ namespace C4IT.LIAM } public static int getDepth(string root, string folder) { - return getDepth(new DirectoryInfo(root), new DirectoryInfo(folder)); + if (string.IsNullOrWhiteSpace(root) || string.IsNullOrWhiteSpace(folder)) + return -1; + + var rootSegments = root.Trim().Replace('/', '\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); + var folderSegments = folder.Trim().Replace('/', '\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); + return folderSegments.Length - rootSegments.Length; } @@ -1030,6 +1094,26 @@ namespace C4IT.LIAM return new List(); } } + public class cLiamNtfsServerRoot : cLiamDataAreaBase + { + public new readonly cLiamProviderNtfs Provider = null; + + public cLiamNtfsServerRoot(cLiamProviderNtfs Provider, string path, int level) : base(Provider) + { + this.Provider = Provider; + this.DisplayName = path.Split('\\').Last(); + this.TechnicalName = path; + this.UID = cLiamNtfsFolder.GetUniqueDataAreaID(path); + this.Level = level; + this.DataType = eLiamDataAreaTypes.NtfsServerRoot; + } + + public override async Task> getChildrenAsync(int Depth = -1) + { + await Task.Delay(0); + return new List(); + } + } public class cLiamAdGroup : cLiamDataAreaBase { public new readonly cLiamProviderNtfs Provider = null;