Files
sharpcompress/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs

99 lines
3.4 KiB
C#
Raw Normal View History

2022-06-19 22:05:52 +02:00
using System.IO;
2015-12-30 11:19:42 +00:00
using SharpCompress.Common.Zip.Headers;
2016-09-26 11:49:49 +01:00
using SharpCompress.Compressors.Deflate;
2015-12-30 11:19:42 +00:00
using SharpCompress.IO;
2022-12-20 15:06:44 +00:00
namespace SharpCompress.Common.Zip;
internal sealed class StreamingZipFilePart : ZipFilePart
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
private Stream? _decompressionStream;
2015-12-30 11:19:42 +00:00
2022-12-20 15:06:44 +00:00
internal StreamingZipFilePart(ZipFileEntry header, Stream stream) : base(header, stream) { }
2022-12-20 15:20:49 +00:00
protected override Stream CreateBaseStream() => Header.PackedStream;
2015-12-30 11:19:42 +00:00
2022-12-20 15:06:44 +00:00
internal override Stream GetCompressedStream()
{
if (!Header.HasData)
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
return Stream.Null;
2015-12-30 11:19:42 +00:00
}
2022-12-20 15:06:44 +00:00
_decompressionStream = CreateDecompressionStream(
GetCryptoStream(CreateBaseStream()),
Header.CompressionMethod
);
if (LeaveStreamOpen)
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
return NonDisposingStream.Create(_decompressionStream);
2015-12-30 11:19:42 +00:00
}
2022-12-20 15:06:44 +00:00
return _decompressionStream;
}
2015-12-30 11:19:42 +00:00
2022-12-20 15:06:44 +00:00
internal BinaryReader FixStreamedFileLocation(ref RewindableStream rewindableStream)
{
if (Header.IsDirectory)
{
return new BinaryReader(rewindableStream);
}
if (Header.HasData && !Skipped)
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
_decompressionStream ??= GetCompressedStream();
if (Header.CompressionMethod != ZipCompressionMethod.None)
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
_decompressionStream.Skip();
// If we had TotalIn / TotalOut we could have used them
Header.CompressedSize = _decompressionStream.Position;
if (_decompressionStream is DeflateStream deflateStream)
{
rewindableStream.Rewind(deflateStream.InputBuffer);
}
2015-12-30 11:19:42 +00:00
}
2022-12-20 15:06:44 +00:00
else
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
// We would need to search for the magic word
rewindableStream.Position -= 4;
var pos = rewindableStream.Position;
while (Utility.Find(rewindableStream, new byte[] { 0x50, 0x4b, 0x07, 0x08 }))
2022-07-28 20:36:28 +02:00
{
2022-12-20 15:06:44 +00:00
// We should probably check CRC32 for positive matching as well
var size = rewindableStream.Position - pos;
var br = new BinaryReader(rewindableStream);
br.ReadUInt32();
br.ReadUInt32(); // CRC32
var compressed_size = br.ReadUInt32();
var uncompressed_size = br.ReadUInt32();
var uncompressed_64bit = br.ReadInt64();
2015-12-30 11:19:42 +00:00
2022-12-20 15:06:44 +00:00
var test_64bit = ((long)uncompressed_size << 32) | compressed_size;
2022-08-04 21:22:31 +02:00
2022-12-20 15:06:44 +00:00
if (test_64bit == size && test_64bit == uncompressed_64bit)
2022-07-28 20:36:28 +02:00
{
2022-12-20 15:06:44 +00:00
Header.CompressedSize = test_64bit;
Header.UncompressedSize = uncompressed_64bit;
rewindableStream.Position -= 24;
break;
2022-07-28 20:36:28 +02:00
}
2022-08-04 21:22:31 +02:00
2022-12-20 15:06:44 +00:00
if (compressed_size == size && compressed_size == uncompressed_size)
{
Header.CompressedSize = compressed_size;
Header.UncompressedSize = uncompressed_size;
rewindableStream.Position -= 24;
break;
}
2022-12-20 15:06:44 +00:00
rewindableStream.Position -= 20;
2015-12-30 11:19:42 +00:00
}
}
2022-12-20 15:06:44 +00:00
Skipped = true;
2015-12-30 11:19:42 +00:00
}
2022-12-20 15:06:44 +00:00
var reader = new BinaryReader(rewindableStream);
_decompressionStream = null;
return reader;
2015-12-30 11:19:42 +00:00
}
2022-06-19 22:05:52 +02:00
}