/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Threading.Tasks; using wasDAVClient; using wasDAVClient.Model; using wasSharp; using wasSharpNET.IO.Utilities; namespace wasStitchNET.Repository { public class Hashing { /// /// Hash local files inside a directory. /// /// the path to a directory to hash /// the partial hash buffer (default: 16384) /// a SHA1 hash of all files in a directory ordered by name public static async Task HashLocalFiles(string path, int bufferSize = 16384) { return await new Task(() => { using (var sha1managed = new SHA1Managed()) { foreach (var stream in Directory .GetFiles(path, "*.*", SearchOption.AllDirectories) .OrderBy(o => o.Split(Path.DirectorySeparatorChar).Last()) .Select(file => IOExtensions.GetWriteStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, STITCH_CONSTANTS.LOCAL_FILE_ACCESS_TIMEOUT))) using (var binaryReader = new BinaryReader(stream)) { var buff = new byte[bufferSize]; int read; while ((read = binaryReader.Read(buff, 0, buff.Length)) != 0) sha1managed.TransformBlock(buff, 0, read, null, 0); } sha1managed.TransformFinalBlock(new byte[] { }, 0, 0); return sha1managed.Hash.ToHexString(); } }); } /// /// Hash the files of a Stitch remote repository release. /// /// the server to hash the release for /// the Stitch release to hash /// the timeout in milliseconds to allow the server to respond /// a SHA1 hash of all files in the release directory ordered by name public static async Task HashRemoteFiles(string server, string update, int timeout) { using (var client = new Client(new NetworkCredential()) { Timeout = timeout, UserAgent = STITCH_CONSTANTS.USER_AGENT.Product.Name, UserAgentVersion = STITCH_CONSTANTS.USER_AGENT.Product.Version, Server = server, BasePath = string.Join(@"/", STITCH_CONSTANTS.UPDATE_PATH, STITCH_CONSTANTS.PROGRESSIVE_PATH) }) { return $"{await HashRemoteFiles(client, string.Join(@"/", update, STITCH_CONSTANTS.UPDATE_DATA_PATH))}"; } } /// /// Hash the files of a Stitch remote repository release using an existing was DAV client. /// /// the was DAV client to use /// the path to the repository release folder /// the partial hash buffer (default: 16384) /// a SHA1 hash of all files in the release directory ordered by name public static async Task HashRemoteFiles(Client client, string path, int bufferSize = 16384) { using (var sha1managed = new SHA1Managed()) { //var list = new List(); foreach (var stream in (await client.List(path, Constants.DavDepth.ALL)) .OrderBy(o => o.DisplayName) .Where(item => !item.IsCollection) .Select(file => client.Download(file.Href))) using (var binaryReader = new BinaryReader(await stream)) { var buff = new byte[bufferSize]; int read; while ((read = binaryReader.Read(buff, 0, buff.Length)) != 0) sha1managed.TransformBlock(buff, 0, read, null, 0); } sha1managed.TransformFinalBlock(new byte[] { }, 0, 0); return sha1managed.Hash.ToHexString(); } } } }