namespace TimelapseApi; using Eto.Forms; public class Protect : TimelapseFileSystem { TimelapseFileSystem fs; public Protect(TimelapseFileSystem fs) { this.fs=fs; } public override void CreateDirectory(string path) { fs.CreateDirectory(path); } public override void DeleteDirectory(string path) { fs.DeleteDirectory(path); } public override void DeleteFile(string path) { fs.DeleteFile(path); } public override bool DirectoryExists(string path) { return fs.DirectoryExists(path); } public override bool FileExists(string path) { return fs.FileExists(path); } public override Stream Open(string path, FileMode mode, FileAccess access, FileShare share) { return fs.Open(path,mode,access,share); } protected override IEnumerable GetDirectoriesImpl(string path, string filter = "*") { foreach(var items in fs.GetDirectories(path,filter)) { yield return CombinePath(path,items); } } public override string? ShowSaveDialog(Window parent, FileFilter[] filters, string startDir = "") { return fs.ShowSaveDialog(parent, filters, startDir); } public override string[] ShowOpenDialog(Window parent, FileFilter[] filters, bool multi, string startDir = "") { return fs.ShowOpenDialog(parent, filters, multi, startDir); } public override string? ShowDirectoryDialog(Window parent, string startDir = "") { return fs.ShowDirectoryDialog(parent,startDir); } protected override IEnumerable GetFilesImpl(string path, string filter = "*") { foreach(var items in fs.GetFiles(path,filter)) { yield return CombinePath(path,items); } } } public class NativeFileSystem : TimelapseFileSystem { public override void CreateDirectory(string path) { Directory.CreateDirectory(path); } public override void DeleteDirectory(string path) { Directory.Delete(path); } public override void DeleteFile(string path) { File.Delete(path); } public override bool DirectoryExists(string path) { return Directory.Exists(path); } public override bool FileExists(string path) { return File.Exists(path); } public override Stream Open(string path, FileMode mode, FileAccess access, FileShare share) { return File.Open(path,mode,access,share); } protected override IEnumerable GetDirectoriesImpl(string path, string filter = "*") { return Directory.EnumerateDirectories(path,filter); } public override string? ShowDirectoryDialog(Window parent, string startDir = "") { using(var d = new SelectFolderDialog()) { if(!string.IsNullOrWhiteSpace(startDir)) { d.Directory = startDir; } return d.ShowDialog(parent) == DialogResult.Ok ? d.Directory : null; } } public override string[] ShowOpenDialog(Window parent, FileFilter[] filters,bool multi, string startDir = "") { using(var ofd=new OpenFileDialog()) { ofd.MultiSelect = multi; if(!string.IsNullOrWhiteSpace(startDir)) { ofd.Directory = new Uri(startDir); } foreach(var f in filters) { ofd.Filters.Add(f); } return ofd.ShowDialog(parent) == DialogResult.Ok ? ofd.Filenames.ToArray() : new string[0]; } } public override string? ShowSaveDialog(Window parent, FileFilter[] filters, string startDir = "") { using(var sfd=new SaveFileDialog()) { if(!string.IsNullOrWhiteSpace(startDir)) { sfd.Directory = new Uri(startDir); } foreach(var f in filters) { sfd.Filters.Add(f); } return sfd.ShowDialog(parent) == DialogResult.Ok ? sfd.FileName : null; } } public override void DeleteDirectory(string path, bool recursive) { Directory.Delete(path,recursive); } protected override IEnumerable GetFilesImpl(string path, string filter = "*") { return Directory.EnumerateFiles(path,filter); } } public abstract class TimelapseFileSystem { public string ReadAllText(string path) { using (var s=Open(path,FileMode.Open,FileAccess.Read,FileShare.Read)) { using(var sr=new StreamReader(s)) { return sr.ReadToEnd(); } } } public void WriteAllText(string path,string? contents) { using (var s=Open(path,FileMode.Create,FileAccess.Write,FileShare.None)) { using(var sw=new StreamWriter(s)) { sw.Write(contents); } } } public string? ShowOpenDialog(Window parent,FileFilter[] filters,string startDir="") { var res=ShowOpenDialog(parent,filters,false,startDir); return res.Length == 1 ? res[0] : null; } public virtual string[] ShowOpenDialog(Window parent,FileFilter[] filters,bool multi,string startDir="") { throw new Exception(); } public virtual string? ShowSaveDialog(Window parent,FileFilter[] filters,string startDir="") { throw new Exception(); } public virtual string? ShowDirectoryDialog(Window parent,string startDir="") { throw new Exception(); } public int GetNumberOfFiles(string path,string filter="*") { return GetFilesImpl(path,filter).Count(); } public int GetNumberOfDirectories(string path,string filter="*") { return GetDirectoriesImpl(path,filter).Count(); } public IEnumerable GetFiles(string path,string filter="*") { foreach(var f in GetFilesImpl(path,filter)) { yield return Path.GetFileName(f); } } public IEnumerable GetDirectories(string path,string filter="*") { foreach(var f in GetDirectoriesImpl(path,filter)) { yield return Path.GetFileName(f); } } public static string CombinePath(params string[] path) { if(path.Length==0) return "/"; string path0=path[0]; foreach(var p in path.Skip(1)) { path0= CombinePath(path0,p); } return path0; } public abstract void DeleteFile(string path); public abstract void DeleteDirectory(string path); public virtual void DeleteDirectory(string path,bool recursive) { if(recursive) { foreach(var d in GetDirectories(path)) { DeleteDirectory(CombinePath(path,d),recursive); } foreach(var f in GetFiles(path)) { DeleteFile(CombinePath(path,f)); } } DeleteDirectory(path); } public abstract void CreateDirectory(string path); public abstract bool FileExists(string path); public abstract bool DirectoryExists(string path); public static string CombinePath(string p1,string p2) { return Path.Combine(p1,p2).Replace(Path.DirectorySeparatorChar,'/'); } public abstract Stream Open(string path,FileMode mode,FileAccess access,FileShare share); protected abstract IEnumerable GetFilesImpl(string path,string filter="*"); protected abstract IEnumerable GetDirectoriesImpl(string path,string filter="*"); public static SubFileSystem operator+(TimelapseFileSystem fs,string name) { SubFileSystem _fs=new SubFileSystem(fs,name); return _fs; } } public class SubFileSystem : TimelapseFileSystem { public SubFileSystem(TimelapseFileSystem fs,string name) { var _fs = fs as SubFileSystem; if(_fs != null) { FileSystem = _fs.FileSystem; CurrentDirectory = CombinePath(_fs.CurrentDirectory,name); }else{ FileSystem =fs; CurrentDirectory = CombinePath("/",name); } } public TimelapseFileSystem FileSystem {get;set;} public string CurrentDirectory {get;set;} public override void CreateDirectory(string path) { FileSystem.CreateDirectory(CombinePath(CurrentDirectory,path)); } public override void DeleteDirectory(string path) { FileSystem.DeleteDirectory(CombinePath(CurrentDirectory,path)); } public override void DeleteFile(string path) { FileSystem.DeleteFile(CombinePath(CurrentDirectory,path)); } public override bool DirectoryExists(string path) { return FileSystem.DirectoryExists(CombinePath(CurrentDirectory,path)); } public override bool FileExists(string path) { return FileSystem.FileExists(CombinePath(CurrentDirectory,path)); } public override Stream Open(string path, FileMode mode, FileAccess access, FileShare share) { return FileSystem.Open(CombinePath(CurrentDirectory,path),mode,access,share); } protected override IEnumerable GetDirectoriesImpl(string path, string filter = "*") { foreach(var file in FileSystem.GetDirectories(CombinePath(CurrentDirectory,path),filter)) { yield return Path.GetFileName(file); } } public override string[] ShowOpenDialog(Window parent, FileFilter[] filters, bool multi, string startDir = "") { string startDir1; if(string.IsNullOrWhiteSpace(startDir)) { startDir1=CurrentDirectory; }else{ startDir1=CombinePath(CurrentDirectory,startDir); } var res=FileSystem.ShowOpenDialog(parent,filters,multi,startDir1); List validUrls=new List(); foreach(var url in res) { if(url.StartsWith(CurrentDirectory)) { validUrls.Add(url); }else { MessageBox.Show($"You can't open file \"{url}\" because it exists outside of \"{CurrentDirectory}\"",MessageBoxButtons.OK,MessageBoxType.Error); } } return validUrls.ToArray(); } public override string? ShowSaveDialog(Window parent, FileFilter[] filters, string startDir = "") { string startDir1; if(string.IsNullOrWhiteSpace(startDir)) { startDir1=CurrentDirectory; }else{ startDir1=CombinePath(CurrentDirectory,startDir); } var url = FileSystem.ShowSaveDialog(parent,filters,startDir1); if(!string.IsNullOrWhiteSpace(url) && !url.StartsWith(CurrentDirectory)) { MessageBox.Show($"You can't save file \"{url}\" because it exists outside of \"{CurrentDirectory}\"",MessageBoxButtons.OK,MessageBoxType.Error); return null; } return url; } public override string? ShowDirectoryDialog(Window parent, string startDir = "") { string startDir1; if(string.IsNullOrWhiteSpace(startDir)) { startDir1=CurrentDirectory; }else{ startDir1=CombinePath(CurrentDirectory,startDir); } var url = FileSystem.ShowDirectoryDialog(parent,startDir1); if(!string.IsNullOrWhiteSpace(url) && !url.StartsWith(CurrentDirectory)) { MessageBox.Show($"You can't open directory \"{url}\" because it exists outside of \"{CurrentDirectory}\"",MessageBoxButtons.OK,MessageBoxType.Error); return null; } return url; } protected override IEnumerable GetFilesImpl(string path, string filter = "*") { foreach(var file in FileSystem.GetFiles(CombinePath(CurrentDirectory,path),filter)) { yield return Path.GetFileName(file); } } public static SubFileSystem operator-(SubFileSystem fs,int num) { string path=fs.CurrentDirectory; for(int i = 0;i < num;i++) { string? p=Path.GetDirectoryName(path); if(string.IsNullOrWhiteSpace(p)) { path="/"; break; }else{ path = p; } } return new SubFileSystem(fs.FileSystem,path); } }