示例#1
0
        /// <summary>
        /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file
        /// </summary>
        /// <param name="fileInfo">A reference to a file on disk.</param>
        /// <param name="downloadCloud">
        /// If the file is hosted in the cloud, the user has the option to include cloud files or not.
        /// </param>
        /// <param name="includeContentHash">If we should generate a hash of the file.</param>
        /// <returns></returns>
        public FileSystemObject FilePathToFileSystemObject(string path)
        {
            FileSystemObject obj = new FileSystemObject(path);

            // Get Owner/Group
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                try
                {
                    var fileSecurity      = new FileSecurity(path, AccessControlSections.Owner);
                    IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier));
                    obj.Owner = AsaHelpers.SidToName(oid);
                }
                catch (Exception e)
                {
                    Log.Verbose("Failed to get owner for {0} ({1}:{2})", path, e.GetType(), e.Message);
                }
                try
                {
                    var fileSecurity      = new FileSecurity(path, AccessControlSections.Group);
                    IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier));
                    obj.Group = AsaHelpers.SidToName(gid);
                }
                catch (Exception e)
                {
                    Log.Verbose("Failed to get group for {0} ({1}:{2})", path, e.GetType(), e.Message);
                }
                try
                {
                    var fileSecurity = new FileSecurity(path, AccessControlSections.Access);
                    var rules        = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier));
                    obj.Permissions = new Dictionary <string, string>();
                    foreach (FileSystemAccessRule?rule in rules)
                    {
                        if (rule != null)
                        {
                            string name = AsaHelpers.SidToName(rule.IdentityReference);

                            foreach (var permission in rule.FileSystemRights.ToString().Split(','))
                            {
                                if (obj.Permissions.ContainsKey(name))
                                {
                                    obj.Permissions[name] = $"{obj.Permissions[name]},{permission}";
                                }
                                else
                                {
                                    obj.Permissions.Add(name, permission);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Verbose("Failed to get FileSecurity for {0} ({1}:{2})", path, e.GetType(), e.Message);
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                try
                {
                    var file = new UnixSymbolicLinkInfo(path);
                    obj.Owner  = file.OwnerUser.UserName;
                    obj.Group  = file.OwnerGroup.GroupName;
                    obj.SetGid = file.IsSetGroup;
                    obj.SetUid = file.IsSetUser;

                    obj.Permissions = new Dictionary <string, string>();
                    if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture))
                    {
                        obj.Permissions.Add("User", "Read,Write,Execute");
                        obj.Permissions.Add("Group", "Read,Write,Execute");
                        obj.Permissions.Add("Other", "Read,Write,Execute");
                    }
                    else
                    {
                        var keys = new List <string>()
                        {
                            "User", "Group", "Other"
                        };
                        var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim());
                        foreach (var key in keys)
                        {
                            foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture)))
                            {
                                if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture))
                                {
                                    obj.Permissions.Add(key, "Read,Write,Execute");
                                }
                                else
                                {
                                    if (obj.Permissions.ContainsKey(key))
                                    {
                                        obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}";
                                    }
                                    else
                                    {
                                        obj.Permissions.Add(key, permission.Trim().Substring(key.Length));
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception e) when(
                    e is ArgumentNullException ||
                    e is ArgumentException ||
                    e is InvalidOperationException)
                {
                    Log.Verbose("Failed to get permissions for {0} ({1}:{2})", path, e.GetType(), e.Message);
                }
            }

            try
            {
                FileIOPermission fiop = new FileIOPermission(FileIOPermissionAccess.Read, path);
                fiop.Demand();
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    if (Directory.Exists(path))
                    {
                        var fileInfo = new DirectoryInfo(path);
                        if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
                        {
                            obj.IsLink = true;
                            obj.Target = NativeMethods.GetFinalPathName(path);
                        }
                        else
                        {
                            obj.IsDirectory = true;
                        }
                    }
                    else
                    {
                        var fileInfo = new FileInfo(path);
                        obj.Size       = fileInfo.Length;
                        obj.SizeOnDisk = WindowsSizeOnDisk(fileInfo);

                        // This check is to try to prevent reading of cloud based files (like a
                        // dropbox folder) and subsequently causing a download, unless the user
                        // specifically requests it with DownloadCloud.
                        if (opts.DownloadCloud || obj.SizeOnDisk > 0 || WindowsFileSystemUtils.IsLocal(obj.Path))
                        {
                            obj.LastModified = File.GetLastWriteTimeUtc(path);
                            obj.Created      = File.GetCreationTimeUtc(path);

                            if (opts.GatherHashes == true)
                            {
                                obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo);
                            }

                            var exeType = FileSystemUtils.GetExecutableType(path);

                            if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN)
                            {
                                obj.IsExecutable = true;
                            }

                            if (exeType == EXECUTABLE_TYPE.WINDOWS)
                            {
                                obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path);
                                obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path);
                            }
                            else if (exeType == EXECUTABLE_TYPE.MACOS)
                            {
                                obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path);
                            }
                        }
                    }
                }
                else
                {
                    UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path);
                    obj.FileType    = i.FileType.ToString();
                    obj.Size        = i.Length;
                    obj.IsDirectory = false;
                    switch (i.FileType)
                    {
                    case FileTypes.SymbolicLink:
                        obj.IsLink = true;
                        obj.Target = i.ContentsPath;
                        break;

                    case FileTypes.Fifo:
                    case FileTypes.Socket:
                    case FileTypes.BlockDevice:
                    case FileTypes.CharacterDevice:
                    case FileTypes.Directory:
                        obj.IsDirectory = true;
                        if (path?.EndsWith(".app", StringComparison.InvariantCultureIgnoreCase) ?? false)
                        {
                            obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path);
                        }
                        break;

                    case FileTypes.RegularFile:
                        var fileInfo = new FileInfo(path);
                        obj.SizeOnDisk = i.BlocksAllocated * i.BlockSize;
                        if (opts.DownloadCloud || obj.SizeOnDisk > 0)
                        {
                            obj.LastModified = File.GetLastWriteTimeUtc(path);
                            obj.Created      = File.GetCreationTimeUtc(path);

                            if (opts.GatherHashes)
                            {
                                obj.ContentHash = FileSystemUtils.GetFileHash(path);
                            }

                            var exeType = FileSystemUtils.GetExecutableType(path);

                            if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN)
                            {
                                obj.IsExecutable = true;
                            }

                            if (exeType == EXECUTABLE_TYPE.WINDOWS)
                            {
                                obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path);
                                obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path);
                            }
                            else if (exeType == EXECUTABLE_TYPE.MACOS)
                            {
                                obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path);
                            }
                        }
                        break;
                    }
                }
            }
            catch (Exception e) when(
                e is ArgumentNullException ||
                e is SecurityException ||
                e is ArgumentException ||
                e is UnauthorizedAccessException ||
                e is PathTooLongException ||
                e is NotSupportedException ||
                e is InvalidOperationException ||
                e is FileNotFoundException ||
                e is Win32Exception ||
                e is IOException)
            {
                Log.Verbose("Failed to create FileInfo from File at {0} ({1}:{2})", path, e.GetType(), e.Message);
            }
            catch (Exception e)
            {
                Log.Debug("Should be caught in DirectoryWalker {0} {1}", e.GetType().ToString(), path);
            }

            try
            {
                obj.LastModified = File.GetLastWriteTimeUtc(path);
                obj.Created      = File.GetCreationTimeUtc(path);
            }
            catch (Exception e)
            {
                Log.Verbose("Failed to get last modified for {0} ({1}:{2})", path, e.GetType(), e.Message);
            }

            return(obj);
        }
        /// <summary>
        /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file
        /// </summary>
        /// <param name="fileInfo">A reference to a file on disk.</param>
        /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param>
        /// <param name="includeContentHash">If we should generate a hash of the file.</param>
        /// <returns></returns>
        public static FileSystemObject FilePathToFileSystemObject(string path, bool downloadCloud = false, bool includeContentHash = false)
        {
            FileSystemObject obj = new FileSystemObject(path);

            // Get Owner/Group
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                try
                {
                    var fileSecurity      = new FileSecurity(path, AccessControlSections.All);
                    IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier));
                    IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier));

                    obj.Owner = AsaHelpers.SidToName(oid);
                    obj.Group = AsaHelpers.SidToName(gid);

                    var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier));
                    foreach (FileSystemAccessRule?rule in rules)
                    {
                        if (rule != null)
                        {
                            string name = AsaHelpers.SidToName(rule.IdentityReference);

                            obj.Permissions = new Dictionary <string, string>();

                            foreach (var permission in rule.FileSystemRights.ToString().Split(','))
                            {
                                if (obj.Permissions.ContainsKey(name))
                                {
                                    obj.Permissions[name] = $"{obj.Permissions[name]},{permission}";
                                }
                                else
                                {
                                    obj.Permissions.Add(name, permission);
                                }
                            }
                        }
                    }
                }
                catch (Exception e) when(
                    e is ArgumentException ||
                    e is ArgumentNullException ||
                    e is DirectoryNotFoundException ||
                    e is FileNotFoundException ||
                    e is IOException ||
                    e is NotSupportedException ||
                    e is PlatformNotSupportedException ||
                    e is PathTooLongException ||
                    e is PrivilegeNotHeldException ||
                    e is SystemException ||
                    e is UnauthorizedAccessException)
                {
                    Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}");
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                try
                {
                    var file = new UnixSymbolicLinkInfo(path);
                    obj.Owner  = file.OwnerUser.UserName;
                    obj.Group  = file.OwnerGroup.GroupName;
                    obj.SetGid = file.IsSetGroup;
                    obj.SetUid = file.IsSetUser;

                    obj.Permissions = new Dictionary <string, string>();
                    if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture))
                    {
                        obj.Permissions.Add("User", "Read,Write,Execute");
                        obj.Permissions.Add("Group", "Read,Write,Execute");
                        obj.Permissions.Add("Other", "Read,Write,Execute");
                    }
                    else
                    {
                        var keys = new List <string>()
                        {
                            "User", "Group", "Other"
                        };
                        var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim());
                        foreach (var key in keys)
                        {
                            foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture)))
                            {
                                if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture))
                                {
                                    obj.Permissions.Add(key, "Read,Write,Execute");
                                }
                                else
                                {
                                    if (obj.Permissions.ContainsKey(key))
                                    {
                                        obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}";
                                    }
                                    else
                                    {
                                        obj.Permissions.Add(key, permission.Trim().Substring(key.Length));
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception e) when(
                    e is ArgumentNullException ||
                    e is ArgumentException ||
                    e is InvalidOperationException)
                {
                    Log.Debug($"Failed to get permissions for {path} {e.GetType().ToString()}");
                }
            }


            try
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    if (Directory.Exists(path))
                    {
                        var fileInfo = new DirectoryInfo(path);
                        if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
                        {
                            obj.IsLink = true;
                            obj.Target = NativeMethods.GetFinalPathName(path);
                        }
                        else
                        {
                            obj.IsDirectory = true;
                        }
                    }
                    else
                    {
                        var fileInfo = new FileInfo(path);
                        var size     = (ulong)fileInfo.Length;
                        obj.Size = size;
                        if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud)
                        {
                            if (includeContentHash)
                            {
                                obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo);
                            }

                            obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, size);

                            if (obj.IsExecutable != null && (bool)obj.IsExecutable)
                            {
                                // TODO: This can be optimized into fewer touches, GetSignatureStatus also runs IsExecutable checks against the first 4 bytes

                                obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path);
                                obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path);
                            }
                        }
                    }
                }
                else
                {
                    UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path);
                    obj.FileType    = i.FileType.ToString();
                    obj.Size        = (ulong)i.Length;
                    obj.IsDirectory = false;
                    switch (i.FileType)
                    {
                    case FileTypes.SymbolicLink:
                        obj.IsLink = true;
                        obj.Target = i.ContentsPath;
                        break;

                    case FileTypes.Fifo:
                    case FileTypes.Socket:
                    case FileTypes.BlockDevice:
                    case FileTypes.CharacterDevice:
                    case FileTypes.Directory:
                        obj.IsDirectory = true;
                        break;

                    case FileTypes.RegularFile:
                        if (i.HasContents)
                        {
                            if (includeContentHash)
                            {
                                obj.ContentHash = FileSystemUtils.GetFileHash(path);
                            }
                            obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, obj.Size);
                        }
                        break;
                    }
                }
            }
            catch (Exception e) when(
                e is ArgumentNullException ||
                e is SecurityException ||
                e is ArgumentException ||
                e is UnauthorizedAccessException ||
                e is PathTooLongException ||
                e is NotSupportedException ||
                e is InvalidOperationException)
            {
                Log.Verbose("Failed to create FileInfo from File at {0} {1}", path, e.GetType().ToString());
            }
            catch (Exception e)
            {
                Log.Debug("Should be caught in DirectoryWalker {0}", e.GetType().ToString());
            }

            try
            {
                obj.LastModified = File.GetLastWriteTimeUtc(path);
                obj.Created      = File.GetCreationTimeUtc(path);
            }
            catch (Exception) { }

            return(obj);
        }