private void SetPermission(IFile file, bool setSubFiles = false, bool setParentFiles = false) { if (setParentFiles) { file.ClearPermission(); SetPermission(file); } if (_group.Rules.ContainsKey(file.VirtualPath)) { file.Permission = _group.Rules[file.VirtualPath]; } else { file.Permission = file.ParentDirectory.Permission; } if (setSubFiles) { VDirectory f = file as VDirectory; if (f == null) { return; } foreach (var s in f.SubFiles) { if (_group.Rules.ContainsKey(s.VirtualPath)) { s.Permission = _group.Rules[s.VirtualPath]; } else { s.Permission = f.Permission; } } } }
/// <summary> /// 获取文件夹 /// </summary> /// <param name="vdir">虚拟路径</param> /// <returns>文件夹信息,如不存在则为null</returns> public DirectoryInfo GetDirectory(string vdir) { string pre = VPath.NormalizeFilename(vdir); VDirectory dir = Get(pre, true) as VDirectory; return(dir == null ? null : dir.RealDirectory); }
public VirtualFileSystem(FtpConfig config, FtpUserGroup group, string rootpath = null) { _config = config; _group = group; if (!string.IsNullOrEmpty(rootpath)) { _rootPath = rootpath; } else if (!string.IsNullOrEmpty(group.HomeDir)) { _rootPath = group.HomeDir; } else { _rootPath = config.HomeDir; } _rootDirectory = new VDirectory(null, new FilePermission("r-xr-xr-x"), _rootPath, ""); _currentDirectory = _rootDirectory; _currentDirectory.Refresh(); AddGroupLinks(); //FIXED:应在刷新后加入链接 _currentDirectory.Refresh(); SetPermission(_currentDirectory, true); }
/// <summary> /// 获取一个虚拟文件实体 /// </summary> /// <param name="vdir">虚拟路径</param> /// <param name="onlyFindDir">只寻找文件夹</param> /// <returns>虚拟文件,如不存在则为null</returns> private IFile Get(string vdir, bool onlyFindDir = false) { IFile currentPosition = _rootDirectory; if (!vdir.Trim().StartsWith("/")) { currentPosition = _currentDirectory; } if (vdir == "") { return(currentPosition); } string pre; string[] dirs = vdir.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < dirs.Length; i++) { pre = dirs[i].Trim(); if (pre == "..") { currentPosition = currentPosition.ParentDirectory; } else { if (currentPosition.IsDirectory) { VDirectory temp = currentPosition as VDirectory; if (temp == null || !temp.Enumerate().Contains(pre)) { return(null); } if (i >= dirs.Length - 1) //找到了最后一层,寻找文件 { if (onlyFindDir) { currentPosition = temp.SubFiles.Find((t) => (t.Name == pre) && (t.IsDirectory)); return(currentPosition ?? _rootDirectory); } //Find:如果找到与指定谓词定义的条件匹配的第一个元素,则为该元素;否则为类型 T 的默认值。 currentPosition = temp.SubFiles.Find((t) => (t.Name == pre) && (!t.IsDirectory)) ?? temp.SubFiles.Find((t) => (t.Name == pre) && (t.IsDirectory)); } else //不是最后一层,找子目录 { currentPosition = temp.SubFiles.Find((t) => (t.Name == pre) && (t.IsDirectory)); } if (currentPosition == null) { return(null); } } } SetPermission(currentPosition); currentPosition.Refresh(); } SetPermission(currentPosition, true, true); return(!currentPosition.Permission.CanRead ? null : currentPosition); }
/// <summary> /// 切换当前目录 /// </summary> /// <param name="vPath">虚拟路径</param> /// <param name="createDirIfNotExists">目录不存在时,是否创建目录</param> //MARK: WARNING: may cause Security Issue! /// <returns></returns> public bool ChangeCurrentDirectory(string vPath, bool createDirIfNotExists = false) { string pre = VPath.NormalizeFilename(vPath, true); if (pre == "..") { _currentDirectory = _currentDirectory.ParentDirectory; } else if (pre == "/") //FIXED: { _currentDirectory = _rootDirectory; } else { VDirectory v; if (pre.StartsWith("/", StringComparison.OrdinalIgnoreCase)) //绝对虚拟路径 { v = Get(pre, true) as VDirectory; } else //相对虚拟路径 { v = _currentDirectory.SubFiles.Find((t) => t.IsDirectory && t.Name == pre) as VDirectory; } if (v == null) { if (!createDirIfNotExists) { return(false); } //ADDED: FileError fileError = CreateDirectory(pre); if (fileError == FileError.None) { var dir = Get(pre, true) as VDirectory; if (dir != null) { v = dir; } else { return(false); } } else { return(false); } } _currentDirectory = v; } _currentDirectory.Refresh(); SetPermission(_currentDirectory, true); return(true); }
public VFile(VDirectory parent, FilePermission permission, string realPath, string name) { ParentDirectory = parent; _permission = permission ?? ParentDirectory.Permission; try { Name = name ?? Path.GetFileName(realPath); RealFile = new FileInfo(realPath); } catch (Exception e) { //throw e; RealFile = null; } }
/// <summary> /// 虚拟文件夹 /// </summary> /// <param name="permission">权限</param> /// <param name="parent">父目录</param> /// <param name="name">文件夹名</param> /// <param name="realPath">真实路径</param> public VDirectory(VDirectory parent, FilePermission permission, string realPath, string name = null) { ParentDirectory = parent; _permission = permission ?? ParentDirectory.Permission; try { Name = name ?? VPath.GetFileName(realPath); if (ParentDirectory == null || ParentDirectory == this) { VirtualPath = "/"; } else { VirtualPath = VPath.Combine(ParentDirectory.VirtualPath, Name); } RealDirectory = new DirectoryInfo(realPath); } catch (Exception e) { //throw e; RealDirectory = null; } }
private List <string> GenerateList(IEnumerable <IFile> list) { List <string> fileList = new List <string>(); DateTime now = DateTime.Now; foreach (var f in list) { if (!f.Permission.CanRead) { continue; } //参考格式 //drwxrwxrwx 1 user group 0 Nov 27 00:13 上传 StringBuilder sb = new StringBuilder(); DateTime editDate; if (f.IsDirectory) { VDirectory vf = (VDirectory)f; editDate = vf.RealDirectory.LastWriteTime; sb.Append('d').Append(f.Permission.ToString()); //文件权限10位 sb.Append(" 1 "); //1空格 子文件个数2位 1空格 sb.Append(string.Format("{0,-8}", _config.Owner.PadRight(8))).Append(' '); //文件所有者8位 1空格 sb.Append(string.Format("{0,-8}", _config.OwnerGroup.PadRight(8))).Append(' '); //文件所有者8位 1空格 //sb.Append(_config.Owner.Substring(0, 8).PadRight(8)).Append(' '); //文件所有者8位 1空格 //sb.Append(_config.OwnerGroup.Substring(0, 8).PadRight(8)).Append(' '); //文件所有组8位 1空格 sb.Append(" 0 "); //文件大小>=8位,文件夹通常为0或4096 1空格 sb.Append(editDate < now.Subtract(TimeSpan.FromDays(180)) //文件修改日期5位,1空格,时间5位,1空格 ? editDate.ToString("MMM dd yyyy", CultureInfo.InvariantCulture) : editDate.ToString("MMM dd HH:mm", CultureInfo.InvariantCulture)) .Append(' '); sb.Append(f.Name); } else { VFile vf = (VFile)f; editDate = vf.RealFile.LastWriteTime; //string.Format("{0,-50}", theObj);//格式化成50个字符,原字符左对齐,不足则补空格 //string.Format("{0,50}", theObj);//格式化成50个字符,原字符右对齐,不足则补空格 sb.Append('-').Append(f.Permission.ToString()); //文件权限10位 sb.Append(" 1 "); //1空格 子文件个数2位 1空格 sb.Append(string.Format("{0,-8}", _config.Owner.PadRight(8))).Append(' '); //文件所有者8位 1空格 sb.Append(string.Format("{0,-8}", _config.OwnerGroup.PadRight(8))).Append(' '); //文件所有者8位 1空格 //sb.Append(_config.OwnerGroup.Substring(0, 8).PadRight(8)).Append(' '); //文件所有组8位 1空格 string length = vf.RealFile.Length.ToString(CultureInfo.InvariantCulture); if (length.Length < 8) { length = length.PadLeft(8); } sb.Append(length).Append(' '); //文件大小>=8位 1空格 sb.Append(editDate < now.Subtract(TimeSpan.FromDays(180)) //文件修改日期5位,1空格,时间5位,1空格 ? editDate.ToString("MMM dd yyyy", CultureInfo.InvariantCulture) : editDate.ToString("MMM dd HH:mm", CultureInfo.InvariantCulture)) .Append(' '); sb.Append(f.Name); } fileList.Add(sb.ToString()); } return(fileList); }
/* perm权限设置 * perm="a" / "c" / "d" / "e" / "f" / "l" / "m" / "p" / "r" / "w" * a:文件,APPE追加许可 * c:文件夹,STOR STOU APPE存储许可(不能已存在) * d:全部,RMD DELE删除许可 * e:文件夹,CWD PWD CDUP目录切换许可 * f:全部,RNFR重命名许可 * l:文件夹,LIST NLST MLSD列目录许可 * m:文件夹,MKD建目录许可 * p:文件夹,DELE文件夹内容删除许可 * r:文件,RTER取得许可 * w:文件,STOR存储许可 */ /// <summary> /// 取得格式化的文件列表 /// <para>MLSD in RFC 3659</para> /// </summary> /// <param name="vPath"></param> /// <returns></returns> public List <string> MachineListFiles(string vPath = null) { VDirectory dir; if (string.IsNullOrEmpty(vPath)) { dir = _currentDirectory; SetPermission(dir, true); } else { dir = Get(VPath.NormalizeFilename(vPath), true) as VDirectory ?? _currentDirectory; } dir.Refresh(); //FIXED:目录及时更新 List <string> fileList = new List <string>(); DateTime now = DateTime.Now; foreach (var f in dir.SubFiles) { if (!f.Permission.CanRead) { continue; } //参考格式 //type=dir;modify=20141218151753;perm=el; 新建文件夹 DateTime editDate; StringBuilder sb = new StringBuilder(); if (f.IsDirectory) { VDirectory vf = (VDirectory)f; editDate = vf.RealDirectory.LastWriteTime.ToUniversalTime(); sb.Append("Type=dir;"); //type类型 sb.Append("modify=").Append(editDate.ToString("yyyyMMddHHmmss")).Append(';'); //modify修改时间 //sb.Append("size=").Append("0"); //文件夹没有size //-RFC 3659- -7.5.5- Its value is always an unordered sequence of alphabetic characters. 意味着权限字母不用排序 sb.Append("perm=el"); //perm权限,具体见上 if (vf.Permission.CanWrite) { sb.Append("cm"); } if (vf.Permission.GroupCanWrite) { sb.Append("dfp"); } sb.Append("; "); sb.Append(f.Name); } else { VFile vf = (VFile)f; editDate = vf.RealFile.LastWriteTime.ToUniversalTime(); //参考格式 //type=file;modify=20140628041312;size=761344; Server.exe sb.Append("type=file;"); //type类型 sb.Append("modify=").Append(editDate.ToString("yyyyMMddHHmmss")).Append(';'); //modify修改时间 sb.Append("size=").Append(vf.RealFile.Length).Append(';'); //size大小 //-RFC 3659- -7.5.5- Its value is always an unordered sequence of alphabetic characters. 意味着权限字母不用排序 sb.Append("perm=r"); //perm权限,具体见上 if (vf.Permission.CanWrite) { //sb.Append("cm"); } if (vf.Permission.GroupCanWrite) { sb.Append("adfw"); } sb.Append("; "); sb.Append(f.Name); } fileList.Add(sb.ToString()); } return(fileList); }