using FileFlows.Plugin; using FileFlows.Plugin.Models; using FileFlows.Plugin.Services; using System.IO; using FileHelper = FileFlows.Plugin.Helpers.FileHelper; namespace PluginTestLibrary; /// /// Local file service /// public class LocalFileService : IFileService { /// /// Gets or sets the path separator for the file system /// public char PathSeparator { get; init; } = Path.DirectorySeparatorChar; public ReplaceVariablesDelegate? ReplaceVariables { get; set; } /// /// Gets or sets the allowed paths the file service can access /// public string[] AllowedPaths { get; init; } = null!; /// /// Gets or sets the permissions to use for files /// public int? Permissions { get; set; } /// /// Gets or sets the owner:group to use for files /// public string OwnerGroup { get; set; } = null!; /// /// Gets or sets the logger used for logging /// public ILogger? Logger { get; set; } public Result GetFiles(string path, string searchPattern = "", bool recursive = false) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { return Directory.GetFiles(path, searchPattern ?? string.Empty, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } catch (Exception) { return new string[] { }; } } public Result GetDirectories(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { return Directory.GetDirectories(path); } catch (Exception) { return new string[] { }; } } public Result DirectoryExists(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { return Directory.Exists(path); } catch (Exception) { return false; } } public Result DirectoryDelete(string path, bool recursive = false) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { Directory.Delete(path, recursive); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result DirectoryMove(string path, string destination) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); if (IsProtectedPath(ref destination)) return Result.Fail("Cannot access protected path: " + destination); try { Directory.Move(path, destination); SetPermissions(destination); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result DirectoryCreate(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { var dirInfo = new DirectoryInfo(path); if (dirInfo.Exists == false) dirInfo.Create(); SetPermissions(path); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result DirectoryCreationTimeUtc(string path) { throw new NotImplementedException(); } public Result DirectoryLastWriteTimeUtc(string path) { throw new NotImplementedException(); } public Result FileExists(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { return System.IO.File.Exists(path); } catch (Exception) { return false; } } public Result FileInfo(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { FileInfo fileInfo = new FileInfo(path); return new FileInformation { CreationTime = fileInfo.CreationTime, CreationTimeUtc = fileInfo.CreationTimeUtc, LastWriteTime = fileInfo.LastWriteTime, LastWriteTimeUtc = fileInfo.LastWriteTimeUtc, Extension = fileInfo.Extension.TrimStart('.'), Name = fileInfo.Name, FullName = fileInfo.FullName, Length = fileInfo.Length, Directory = fileInfo.DirectoryName! }; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileDelete(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { var fileInfo = new FileInfo(path); if(fileInfo.Exists) fileInfo.Delete(); return true; } catch (Exception) { return false; } } public Result FileSize(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { var fileInfo = new FileInfo(path); if (fileInfo.Exists == false) return Result.Fail("File does not exist"); return fileInfo.Length; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileCreationTimeUtc(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { var fileInfo = new FileInfo(path); if (fileInfo.Exists == false) return Result.Fail("File does not exist"); return fileInfo.CreationTimeUtc; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileLastWriteTimeUtc(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { var fileInfo = new FileInfo(path); if (fileInfo.Exists == false) return Result.Fail("File does not exist"); return fileInfo.LastWriteTimeUtc; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileMove(string path, string destination, bool overwrite = true) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); if (IsProtectedPath(ref destination)) return Result.Fail("Cannot access protected path: " + destination); try { var fileInfo = new FileInfo(path); if (fileInfo.Exists == false) return Result.Fail("File does not exist"); var destDir = new FileInfo(destination).Directory!; if (destDir.Exists == false) { destDir.Create(); SetPermissions(destDir.FullName); } fileInfo.MoveTo(destination, overwrite); SetPermissions(destination); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileCopy(string path, string destination, bool overwrite = true) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); if (IsProtectedPath(ref destination)) return Result.Fail("Cannot access protected path: " + destination); try { var fileInfo = new FileInfo(path); if (fileInfo.Exists == false) return Result.Fail("File does not exist"); var destDir = new FileInfo(destination).Directory!; if (destDir.Exists == false) { destDir.Create(); SetPermissions(destDir.FullName); } fileInfo.CopyTo(destination, overwrite); SetPermissions(destination); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public Result FileAppendAllText(string path, string text) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { System.IO.File.AppendAllText(path, text); SetPermissions(path); return true; } catch (Exception ex) { return Result.Fail(ex.Message); } } public bool FileIsLocal(string path) => true; /// /// Gets the local path /// /// the path /// the local path to the file public Result GetLocalPath(string path) => Result.Success(path); public Result Touch(string path) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); if (DirectoryExists(path).Is(true)) { try { Directory.SetLastWriteTimeUtc(path, DateTime.UtcNow); return true; } catch (Exception ex) { return Result.Fail("Failed to touch directory: " + ex.Message); } } try { if (System.IO.File.Exists(path)) System.IO.File.SetLastWriteTimeUtc(path, DateTime.UtcNow); else { System.IO.File.Create(path); SetPermissions(path); } return true; } catch (Exception ex) { return Result.Fail($"Failed to touch file: '{path}' => {ex.Message}"); } } public Result DirectorySize(string path) { if (string.IsNullOrWhiteSpace(path)) return 0; if (System.IO.File.Exists(path)) path = new FileInfo(path).Directory?.FullName ?? string.Empty; if (string.IsNullOrWhiteSpace(path)) return 0; if (Directory.Exists(path) == false) return 0; try { DirectoryInfo dir = new DirectoryInfo(path); return dir.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(x => x.Length); } catch (Exception) { return 0; } } public Result SetCreationTimeUtc(string path, DateTime date) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { if (!System.IO.File.Exists(path)) return Result.Fail("File not found."); System.IO.File.SetCreationTimeUtc(path, date); return Result.Success(true); } catch (Exception ex) { return Result.Fail($"Error setting creation time: {ex.Message}"); } } public Result SetLastWriteTimeUtc(string path, DateTime date) { if (IsProtectedPath(ref path)) return Result.Fail("Cannot access protected path: " + path); try { if (!System.IO.File.Exists(path)) return Result.Fail("File not found."); System.IO.File.SetLastWriteTimeUtc(path, date); return Result.Success(true); } catch (Exception ex) { return Result.Fail($"Error setting last write time: {ex.Message}"); } } /// /// Checks if a path is accessible by the file server /// /// the path to check /// true if accessible, otherwise false private bool IsProtectedPath(ref string path) { if (OperatingSystem.IsWindows()) path = path.Replace("/", "\\"); else path = path.Replace("\\", "/"); if(ReplaceVariables != null) path = ReplaceVariables(path, true); if (FileHelper.IsSystemDirectory(path)) return true; // a system directory, no access if (AllowedPaths?.Any() != true) return false; // no allowed paths configured, allow all if (OperatingSystem.IsWindows()) path = path.ToLowerInvariant(); for(int i=0;i? logMethod = null) { logMethod ??= (string message) => Logger?.ILog(message); permissions = permissions != null && permissions > 0 ? permissions : Permissions; if (permissions == null || permissions < 1) permissions = 777; if ((System.IO.File.Exists(path) == false && Directory.Exists(path) == false)) { logMethod("SetPermissions: File doesnt existing, skipping"); return; } //StringLogger stringLogger = new StringLogger(); var logger = new TestLogger(); bool isFile = new FileInfo(path).Exists; FileHelper.SetPermissions(logger, path, file: isFile, permissions: permissions); FileHelper.ChangeOwner(logger, path, file: isFile, ownerGroup: OwnerGroup); logMethod(logger.ToString()); } }