public static string SHA256(string filename) { using (var os = File.OpenRead(filename)) { var hasher = new SHA256CryptoServiceProvider(); return(HashingStream.ToHex(hasher.ComputeHash(os))); }; }
private async Task <IEnumerable <ArchiveContents> > GetDownloadMetadata(IProgress <string> progress) { var ini_files = Directory.EnumerateFiles(_transcompilerBase.MODirectory, "meta.ini", SearchOption.AllDirectories) .AsParallel() .Select(f => (new FileIniDataParser()).ReadFile(f)) .ToList(); var archives = Directory.EnumerateFiles(_transcompilerBase.DownloadsDirectoryPath, "*.*"); var tasks = archives.AsParallel() .Select(async archive => { if (!SUPPORTED_ARCHIVES.Contains(Path.GetExtension(archive).ToLower())) { return; } var meta_data_path = Path.Combine(_transcompilerBase.DownloadsDirectoryPath, archive) + METADATA_EXTENSION; if (File.Exists(meta_data_path)) { return; } Update(progress, "[META] Generating Metadata for: ", Path.GetFileName(archive)); using (var archive_file = new ArchiveFile(archive)) { // Extract the contents of the file and attach each to a hashing stream var streams = new Dictionary <string, HashingStream>(); archive_file.Extract(e => { if (e.IsFolder) { return(null); } if (streams.ContainsKey(e.FileName)) { return(streams[e.FileName]); } var stream = new HashingStream(e.FileName); streams.Add(e.FileName, stream); return(stream); }); var contents = from stream in streams.Values select new ArchiveEntry { FileName = stream.Filename, MD5 = stream.MD5Hash, SHA256 = stream.SHA256Hash, Size = stream.Size.ToString() }; var ac = new ArchiveContents(); using (var file = File.OpenRead(archive)) { var hasher = new MD5CryptoServiceProvider(); hasher.ComputeHash(file); ac.MD5 = HashingStream.ToHex(hasher.Hash); } using (var file = File.OpenRead(archive)) { var hasher = new SHA256CryptoServiceProvider(); hasher.ComputeHash(file); ac.SHA256 = HashingStream.ToHex(hasher.Hash); } ac.DiskName = Path.GetFileName(archive); ac.FileSize = (new FileInfo(archive)).Length.ToString(); ac.Contents = contents.ToArray(); // Look for an .meta file next to the archive itself var meta_path = archive + ".meta"; bool found_ini = false; if (File.Exists(meta_path)) { var meta_ini = (new FileIniDataParser()).ReadFile(meta_path); var general = meta_ini["General"]; ac.NexusModId = general["modID"]; ac.NexusFileId = general["fileID"]; ac.TargetGame = general["gameName"]; ac.ModName = general["modName"]; ac.Version = general["version"]; ac.Repository = general["repository"]; } if (found_ini == false) { // Try to find a matching .meta file in a mod that uses this archive var archive_file_name = Path.GetFileName(archive); var match = ini_files.Where(d => Path.GetFileName(d.GetIn("General", "installationFile")) == archive_file_name) .FirstOrDefault(); if (match != null) { var general = match["General"]; ac.TargetGame = general["gameName"]; ac.Repository = general["repository"]; } } // Try to find a matching nexus mod var result = await _nexusApi.GetModsByMd5(new IntermediaryModObject { Md5 = ac.MD5, TrueArchiveName = ac.DiskName, TargetGame = ac.TargetGame }); if (result != null) { ac.Author = result.AuthorName; ac.NexusModId = result.ModId; ac.NexusFileName = result.NexusFileName; ac.NexusFileId = result.FileId; ac.Version = result.Version; ac.FileSize = (new FileInfo(archive)).Length.ToString(); } await WriteJSON(meta_data_path, ac); Update(progress, "[META] Finished", Path.GetFileName(archive)); } }); await Task.WhenAll(tasks); ConcurrentStack <ArchiveContents> loaded = new ConcurrentStack <ArchiveContents>(); var result_tasks = Directory.EnumerateFiles(_transcompilerBase.DownloadsDirectoryPath, "*" + METADATA_EXTENSION) .AsParallel() .Select(async file => { using (var r = new StreamReader(File.OpenRead(file))) { return(JsonConvert.DeserializeObject <ArchiveContents>(await r.ReadToEndAsync())); } }); await Task.WhenAll(result_tasks); var results = result_tasks.Select(t => t.Result).ToList(); return(results); }