private MS2File(MS2FileInfoHeader infoHeader, MS2FileHeader header, MS2CryptoMode archiveCryptoMode, MemoryMappedFile dataFile) { this.InfoHeader = infoHeader ?? throw new ArgumentNullException(nameof(infoHeader)); this.Header = header ?? throw new ArgumentNullException(nameof(header)); this.ArchiveCryptoMode = archiveCryptoMode; this.DataMemoryMappedFile = dataFile ?? throw new ArgumentNullException(nameof(dataFile)); this.CompressionType = this.Header.CompressionType; this.IsDataEncrypted = true; }
internal static async Task <MS2File> Load(MS2CryptoMode cryptoMode, Stream headerStream, Stream dataStream, MemoryMappedFile dataMemoryMappedFile) { MS2FileInfoHeader fileInfoHeader = await MS2FileInfoHeader.Load(headerStream).ConfigureAwait(false); MS2FileHeader fileHeader = await MS2FileHeader.Load(cryptoMode, dataStream).ConfigureAwait(false); DLogger.Write($"Id={fileInfoHeader.Id}-{fileHeader.Id}, CompressionId={fileHeader.CompressionType}, RootFolder={fileInfoHeader.RootFolderId}, Name={fileInfoHeader.Name}, Size={FileEx.FormatStorage(fileHeader.EncodedSize)}->{FileEx.FormatStorage(fileHeader.CompressedSize)}->{FileEx.FormatStorage(fileHeader.Size)}"); var file = new MS2File(fileInfoHeader, fileHeader, cryptoMode, dataMemoryMappedFile); return(file); }
private MS2File(MS2FileInfoHeader infoHeader, MS2FileHeader header, MS2CryptoMode archiveCryptoMode, Stream dataStream) { if (!dataStream.CanSeek) { throw new ArgumentException("Stream must be seekable.", nameof(dataStream)); } this.InfoHeader = infoHeader ?? throw new ArgumentNullException(nameof(infoHeader)); this.Header = header ?? throw new ArgumentNullException(nameof(header)); this.ArchiveCryptoMode = archiveCryptoMode; this.DataStream = dataStream ?? throw new ArgumentNullException(nameof(dataStream)); this.CompressionType = this.Header.CompressionType; this.IsDataEncrypted = true; }
private static async Task SaveSync(MS2CryptoMode cryptoMode, MS2File[] files, Stream headerStream, Stream dataStream) { MS2SizeHeader header; MS2SizeHeader dataHeader; Stream encryptedHeaderStream; Stream encryptedDataHeaderStream; using (var archiveInfoHeaderStream = new MemoryStream()) using (var archiveHeaderStream = new MemoryStream()) { for (int i = 0; i < files.Length; i++) { MS2File file = files[i]; uint offset = (uint)dataStream.Position; (Stream Stream, bool ShouldDispose, MS2SizeHeader Header)data = await file.GetEncryptedStreamAsync().ConfigureAwait(false); try { var fileHeader = MS2FileHeader.Create(file.Id, offset, file.CompressionType, data.Header); await file.InfoHeader.Save(archiveInfoHeaderStream).ConfigureAwait(false); await fileHeader.Save(cryptoMode, archiveHeaderStream).ConfigureAwait(false); await data.Stream.CopyToAsync(dataStream).ConfigureAwait(false); } finally { if (data.ShouldDispose) { data.Stream.Dispose(); } } } archiveInfoHeaderStream.Position = 0; archiveHeaderStream.Position = 0; // TODO: are those always compressed? (encryptedHeaderStream, header) = await EncryptStreamToStreamAsync(cryptoMode, true, archiveInfoHeaderStream, (uint)archiveInfoHeaderStream.Length).ConfigureAwait(false); (encryptedDataHeaderStream, dataHeader) = await EncryptStreamToStreamAsync(cryptoMode, true, archiveHeaderStream, (uint)archiveHeaderStream.Length).ConfigureAwait(false); } using (var bwHeader = new BinaryWriter(headerStream, Encoding.ASCII, true)) { switch (cryptoMode) { case MS2CryptoMode.MS2F: await SaveMS2F(cryptoMode, (uint)files.Length, header, dataHeader, bwHeader).ConfigureAwait(false); break; case MS2CryptoMode.NS2F: await SaveNS2F(cryptoMode, (uint)files.Length, header, dataHeader, bwHeader).ConfigureAwait(false); break; default: case MS2CryptoMode.OS2F: case MS2CryptoMode.PS2F: throw new NotImplementedException(); } } using (encryptedHeaderStream) using (encryptedDataHeaderStream) { await encryptedHeaderStream.CopyToAsync(headerStream).ConfigureAwait(false); await encryptedDataHeaderStream.CopyToAsync(headerStream).ConfigureAwait(false); } }