public FileInformation AddProperties(Stream stream, FileProperties requiredProperties) { requiredProperties -= requiredProperties & GetProperties(); if (Size == null && (requiredProperties.HasFlag(FileProperties.Size) || requiredProperties.HasFlag(FileProperties.BlockSize) || (requiredProperties & FileProperties.AllBlockHashes) != FileProperties.None || (requiredProperties & FileProperties.AllHashes) != FileProperties.None)) { Size = stream.Length; } if (BlockSize == null && (requiredProperties & (FileProperties.BlockSize | FileProperties.AllHashes | FileProperties.AllBlockHashes)) != FileProperties.None) { BlockSize = GetBlockSize(Size.Value); } int readLength = 0; byte[] buffer = new byte[BlockSize == null ? SliceLength : BlockSize.Value]; if (stream != null && stream.CanSeek) { // Assume at head if stream is not seekable. stream.Seek(0, SeekOrigin.Begin); } if (requiredProperties.HasFlag(FileProperties.SliceMD5)) { readLength = stream.Read(buffer, 0, SliceLength); SliceMD5 = (readLength == SliceLength) ? new MD5CryptoServiceProvider().ComputeHash(buffer, 0, SliceLength).ToHexString() : null; } if ((requiredProperties & FileProperties.AllHashes) != FileProperties.None) { List<HashAlgorithm> hashers = new List<HashAlgorithm> { requiredProperties.HasFlag(FileProperties.MD5) ? new MD5CryptoServiceProvider() : null, requiredProperties.HasFlag(FileProperties.SHA1) ? new SHA1CryptoServiceProvider() : null, requiredProperties.HasFlag(FileProperties.SHA256) ? new SHA256CryptoServiceProvider() : null }; BlockMD5 = requiredProperties.HasFlag(FileProperties.BlockMD5) ? new List<string>() : BlockMD5; BlockSHA1 = requiredProperties.HasFlag(FileProperties.BlockSHA1) ? new List<string>() : BlockSHA1; BlockSHA256 = requiredProperties.HasFlag(FileProperties.BlockSHA256) ? new List<string>() : BlockSHA256; List<HashAlgorithm> blockHashers = new List<HashAlgorithm> { requiredProperties.HasFlag(FileProperties.BlockMD5) ? new MD5CryptoServiceProvider() : null, requiredProperties.HasFlag(FileProperties.BlockSHA1) ? new SHA1CryptoServiceProvider() : null, requiredProperties.HasFlag(FileProperties.BlockSHA256) ? new SHA256CryptoServiceProvider() : null }; List<IHash> additionalHashers = new List<IHash> { requiredProperties.HasFlag(FileProperties.CRC32) ? HashFactory.Checksum.CreateCRC32a() : null, requiredProperties.HasFlag(FileProperties.Adler32) ? HashFactory.Checksum.CreateAdler32() : null }; foreach (var hasher in additionalHashers) { hasher?.Initialize(); } while ((readLength += stream.Read(buffer, readLength, BlockSize.Value - readLength)) != 0) { Parallel.ForEach( hashers, hasher => { hasher?.TransformBlock(buffer, 0, readLength, buffer, 0); } ); Parallel.ForEach( additionalHashers, hasher => { hasher?.TransformBytes(buffer, 0, readLength); } ); if (requiredProperties.HasFlag(FileProperties.BlockMD5)) { BlockMD5.Add(blockHashers[0].ComputeHash(buffer, 0, readLength).ToHexString()); } if (requiredProperties.HasFlag(FileProperties.BlockSHA1)) { BlockSHA1.Add(blockHashers[1].ComputeHash(buffer, 0, readLength).ToHexString()); } if (requiredProperties.HasFlag(FileProperties.BlockSHA256)) { BlockSHA256.Add(blockHashers[2].ComputeHash(buffer, 0, readLength).ToHexString()); } readLength = 0; } foreach (var hasher in hashers) { hasher?.TransformFinalBlock(buffer, 0, 0); } MD5 = MD5 ?? hashers[0]?.Hash.ToHexString(); SHA1 = SHA1 ?? hashers[1]?.Hash.ToHexString(); SHA256 = SHA256 ?? hashers[2]?.Hash.ToHexString(); CRC32 = CRC32 ?? additionalHashers[0]?.TransformFinal().GetBytes().Reverse().ToArray().ToHexString(); Adler32 = Adler32 ?? additionalHashers[1]?.TransformFinal().GetBytes().Reverse().ToArray().ToHexString(); } if (requiredProperties.HasFlag(FileProperties.EncryptionKey)) { EncryptionKey = GenerateEncryptionKey(); } return this; }
public static FileInformation GetInformation(string basePath, string path, FileProperties requiredProperties) { FileInformation info = GetInformation(File.OpenRead($"{basePath}/{path}"), requiredProperties); if (requiredProperties.HasFlag(FileProperties.Path)) { info.Path = path.Replace(System.IO.Path.DirectorySeparatorChar, '/'); } return info; }
public FileInformation RemoveProperties(FileProperties removedProperties) { foreach (var p in Properties) { if (removedProperties.HasFlag(p.Key)) { p.Value.SetValue(this, null); } } return this; }
public FileProperties CompareProperties(FileInformation other, FileProperties propertiesToCompare) { FileProperties result = FileProperties.None; foreach (var p in Properties) { if (propertiesToCompare.HasFlag(p.Key)) { if (p.Value.GetValue(other) != null) { if (p.Value.PropertyType.IsAssignableFrom(typeof(List<string>))) { var olist = p.Value.GetValue(other) as List<string>; var tlist = p.Value.GetValue(this) as List<string>; if (!tlist.SequenceEqual(olist)) { result |= p.Key; } } else if (!object.Equals(p.Value.GetValue(other), p.Value.GetValue(this))) { result |= p.Key; } } } } return result; }
public FileInformation GetInfo( FileProperties propertiesToRemove = FileProperties.None, FileProperties requiredProperties = FileProperties.All) { using (var stream = OpenRead()) { var info = FileInformation.Get(Path) .RemoveProperties(propertiesToRemove) .AddProperties(stream, requiredProperties); if (requiredProperties.HasFlag(FileProperties.Path) && info.Path == null) { info.Path = Path; } if (requiredProperties.HasFlag(FileProperties.Locations)) { if (info.Locations == null) info.Locations = new Dictionary<string, string>(); info.Locations[Spec] = ToString(); } return info; } }