diff --git a/2021/11/AccessibleDirectory.cs b/2021/11/AccessibleDirectory.cs new file mode 100644 index 0000000..a4af53d --- /dev/null +++ b/2021/11/AccessibleDirectory.cs @@ -0,0 +1,381 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace RyzStudio.IO +{ + public class AccessibleDirectory + { + + public static List GetFiles(string path, string pattern, bool searchTopOnly) + { + List fileList = new List(); + List directoryList = new List(); + + if (string.IsNullOrWhiteSpace(pattern)) pattern = "*"; + + directoryList.Add(path); + + while (true) + { + if (directoryList.Count <= 0) + { + break; + } + + string directory = directoryList.First(); + directoryList.RemoveAt(0); + + if (IsDirectoryAccessible(directory)) + { + IEnumerable searchDirList = new List(); + + try + { + searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly); + } + catch (Exception) + { + continue; + } + + if (!searchTopOnly) + { + foreach (string item in searchDirList) + { + if (!IsDirectoryAccessible(item)) + { + continue; + } + + directoryList.Add(item); + } + } + + foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)) + { + if (!MatchFileSearchPattern(pattern, Path.GetFileName(item))) + { + continue; + } + + if (!IsFileAccessible(item)) + { + continue; + } + + fileList.Add(item); + } + } + } + + return fileList; + } + + public static IEnumerable EnumerateFiles(string path, string pattern, bool searchTopOnly) + { + List directoryList = new List(); + + if (string.IsNullOrWhiteSpace(pattern)) pattern = "*"; + + directoryList.Add(path); + + while (true) + { + if (directoryList.Count <= 0) + { + yield break; + } + + string directory = directoryList.First(); + directoryList.RemoveAt(0); + + if (IsDirectoryAccessible(directory)) + { + IEnumerable searchDirList = new List(); + + try + { + searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly); + } + catch (Exception) + { + continue; + } + + if (!searchTopOnly) + { + foreach (string item in searchDirList) + { + if (!IsDirectoryAccessible(item)) + { + continue; + } + + directoryList.Add(item); + } + } + + foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)) + { + if (!MatchFileSearchPattern(pattern, Path.GetFileName(item))) + { + continue; + } + + if (!IsFileAccessible(item)) + { + continue; + } + + yield return item; + } + } + } + } + + public static void GetFiles(string path, string pattern, bool searchTopOnly, Func callback) + { + List directoryList = new List(); + ulong searchCount = 0; + + if (string.IsNullOrWhiteSpace(pattern)) pattern = "*"; + + directoryList.Add(path); + searchCount++; + + while (true) + { + if (directoryList.Count <= 0) + { + break; + } + + string directory = directoryList.First(); + directoryList.RemoveAt(0); + + callback(null, searchCount, directoryList.Count); + + if (IsDirectoryAccessible(directory)) + { + IEnumerable searchDirList = new List(); + + try + { + searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly); + } + catch (Exception) + { + continue; + } + + if (!searchTopOnly) + { + foreach (string item in searchDirList) + { + if (!IsDirectoryAccessible(item)) + { + continue; + } + + directoryList.Add(item); + searchCount++; + + callback(null, searchCount, directoryList.Count); + } + } + + foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)) + { + if (!MatchFileSearchPattern(pattern, Path.GetFileName(item))) + { + continue; + } + + if (!IsFileAccessible(item)) + { + continue; + } + + callback(item, searchCount, directoryList.Count); + } + } + } + } + + public static string GetNextFile(string filepath, string pattern) + { + if (string.IsNullOrWhiteSpace(filepath)) return null; + + string path = Path.GetDirectoryName(filepath); + if (string.IsNullOrWhiteSpace(path)) return null; + + string filename = Path.GetFileName(filepath); + if (string.IsNullOrWhiteSpace(filename)) return null; + + List fileList = AccessibleDirectory.GetFiles(path, pattern, true); + if (fileList == null) return null; + if (fileList.Count <= 0) return null; + if (fileList.Count(x => (Path.GetFileName(x).Equals(filename))) < 0) return null; + + int pos = fileList.FindIndex(x => Path.GetFileName(x).Equals(filename)); + if (pos < 0) return null; + if (pos >= (fileList.Count - 1)) return null; + + return fileList[(pos + 1)]; + } + + public static bool IsAccessible(string path) + { + if (string.IsNullOrWhiteSpace(path)) return false; + + if (File.Exists(path)) return IsFileAccessible(path); + if (Directory.Exists(path)) return IsDirectoryAccessible(path); + + return false; + } + + public static bool IsFileAccessible(string filename) + { + if (string.IsNullOrWhiteSpace(filename)) return false; + if (!File.Exists(filename)) return false; + + try + { + FileInfo fi = new FileInfo(filename); + fi.GetAccessControl(); + } + catch + { + return false; + } + + return true; + } + + public static bool IsDirectoryAccessible(string path) + { + if (string.IsNullOrWhiteSpace(path)) return false; + if (!Directory.Exists(path)) return false; + + try + { + DirectoryInfo di = new DirectoryInfo(path); + di.GetAccessControl(); + } + catch + { + return false; + } + + return true; + } + + public static bool MatchFileSearchPattern(string pattern, string subject) + { + if (string.IsNullOrWhiteSpace(pattern)) + { + return false; + } + + Func matchPattern = (pattern, subject) => + { + string[] parts = pattern.Split('*'); + if (parts.Length <= 1) + { + return subject.Equals(pattern, StringComparison.CurrentCultureIgnoreCase); + } + + int pos = 0; + + for (int i = 0; i < parts.Length; i++) + { + if (i <= 0) + { + // first + pos = subject.IndexOf(parts[i], pos, StringComparison.CurrentCultureIgnoreCase); + if (pos != 0) + { + return false; + } + } + else if (i >= (parts.Length - 1)) + { + // last + if (!subject.EndsWith(parts[i], StringComparison.CurrentCultureIgnoreCase)) + { + return false; + } + } + else + { + pos = subject.IndexOf(parts[i], pos, StringComparison.CurrentCultureIgnoreCase); + if (pos < 0) + { + return false; + } + + pos += parts[i].Length; + } + } + + return true; + }; + + Func matchAllPattern = (pattern, subject) => + { + int wildcardCount = pattern.Count(x => x.Equals('*')); + if (wildcardCount <= 0) + { + return subject.Equals(pattern, StringComparison.CurrentCultureIgnoreCase); + } + else if (wildcardCount == 1) + { + string newWildcardPattern = pattern.Replace("*", ""); + + if (pattern.StartsWith("*")) + { + return subject.EndsWith(newWildcardPattern, StringComparison.CurrentCultureIgnoreCase); + } + else if (pattern.EndsWith("*")) + { + return subject.StartsWith(newWildcardPattern, StringComparison.CurrentCultureIgnoreCase); + } + else + { + return matchPattern(pattern, subject); + } + } + else + { + return matchPattern(pattern, subject); + } + }; + + if (pattern.Contains(';')) + { + string[] parts = pattern.Split(';'); + for (int i=0; i