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

103 lines
3.8 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;
namespace SharpCompress.Common.Zip
{
2020-05-23 16:27:55 -07:00
internal sealed class StreamingZipFilePart : ZipFilePart
2015-12-30 11:19:42 +00:00
{
2020-05-23 16:27:55 -07:00
private Stream? _decompressionStream;
2015-12-30 11:19:42 +00:00
2022-12-20 13:45:47 +00:00
internal StreamingZipFilePart(ZipFileEntry header, Stream stream) : base(header, stream) { }
2015-12-30 11:19:42 +00:00
protected override Stream CreateBaseStream()
{
return Header.PackedStream;
}
internal override Stream GetCompressedStream()
{
if (!Header.HasData)
{
return Stream.Null;
}
2022-12-20 13:45:47 +00:00
_decompressionStream = CreateDecompressionStream(
GetCryptoStream(CreateBaseStream()),
Header.CompressionMethod
);
2015-12-30 11:19:42 +00:00
if (LeaveStreamOpen)
{
2022-06-19 22:05:52 +02:00
return NonDisposingStream.Create(_decompressionStream);
2015-12-30 11:19:42 +00:00
}
2018-05-06 08:59:00 +01:00
return _decompressionStream;
2015-12-30 11:19:42 +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
{
2020-05-23 16:27:55 -07:00
_decompressionStream ??= GetCompressedStream();
2021-01-09 13:33:34 +00:00
2022-12-20 13:45:47 +00:00
if (Header.CompressionMethod != ZipCompressionMethod.None)
2022-07-28 20:36:28 +02:00
{
_decompressionStream.Skip();
2015-12-30 11:19:42 +00:00
2022-08-04 21:22:31 +02:00
// If we had TotalIn / TotalOut we could have used them
Header.CompressedSize = _decompressionStream.Position;
2022-07-28 20:36:28 +02:00
if (_decompressionStream is DeflateStream deflateStream)
{
rewindableStream.Rewind(deflateStream.InputBuffer);
}
}
else
2015-12-30 11:19:42 +00:00
{
2022-07-28 20:36:28 +02:00
// We would need to search for the magic word
rewindableStream.Position -= 4;
var pos = rewindableStream.Position;
2022-12-20 13:45:47 +00:00
while (Utility.Find(rewindableStream, new byte[] { 0x50, 0x4b, 0x07, 0x08 }))
{
// 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();
2022-08-04 21:22:31 +02:00
var uncompressed_64bit = br.ReadInt64();
long test_64bit = (long)uncompressed_size << 32 | (long)compressed_size;
2022-12-20 13:45:47 +00:00
if (test_64bit == size && test_64bit == uncompressed_64bit)
2022-08-04 21:22:31 +02:00
{
Header.CompressedSize = test_64bit;
Header.UncompressedSize = uncompressed_64bit;
rewindableStream.Position -= 24;
break;
}
2022-12-20 13:45:47 +00:00
if (compressed_size == size && compressed_size == uncompressed_size)
{
2022-08-04 21:22:31 +02:00
Header.CompressedSize = compressed_size;
Header.UncompressedSize = uncompressed_size;
rewindableStream.Position -= 24;
break;
}
2022-08-04 21:22:31 +02:00
rewindableStream.Position -= 20;
}
2015-12-30 11:19:42 +00:00
}
2022-07-28 20:36:28 +02:00
Skipped = true;
2015-12-30 11:19:42 +00:00
}
var reader = new BinaryReader(rewindableStream);
2018-05-06 08:59:00 +01:00
_decompressionStream = null;
2015-12-30 11:19:42 +00:00
return reader;
}
}
2022-06-19 22:05:52 +02:00
}