diff --git a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs index 9b333038..ee0c6be9 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs @@ -47,6 +47,9 @@ namespace SharpCompress.Common.Zip { _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); @@ -66,12 +69,26 @@ namespace SharpCompress.Common.Zip br.ReadUInt32(); // CRC32 var compressed_size = br.ReadUInt32(); var uncompressed_size = br.ReadUInt32(); - if (compressed_size == size && compressed_size == uncompressed_size ) + var uncompressed_64bit = br.ReadInt64(); + + long test_64bit = (long)uncompressed_size << 32 | (long)compressed_size; + + if( test_64bit == size && test_64bit == uncompressed_64bit ) { - rewindableStream.Position -= 16; + Header.CompressedSize = test_64bit; + Header.UncompressedSize = uncompressed_64bit; + rewindableStream.Position -= 24; break; } - rewindableStream.Position -= 12; + + if (compressed_size == size && compressed_size == uncompressed_size ) + { + Header.CompressedSize = compressed_size; + Header.UncompressedSize = uncompressed_size; + rewindableStream.Position -= 24; + break; + } + rewindableStream.Position -= 20; } } diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 3c273e32..836fb039 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using SharpCompress.Common.Zip.Headers; using SharpCompress.IO; @@ -28,6 +28,7 @@ namespace SharpCompress.Common.Zip { ZipHeader? header; BinaryReader reader = new BinaryReader(rewindableStream); + uint headerBytes = 0; if (_lastEntryHeader != null && (FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) || _lastEntryHeader.IsZip64)) { @@ -39,15 +40,37 @@ namespace SharpCompress.Common.Zip crc = reader.ReadUInt32(); } _lastEntryHeader.Crc = crc; - _lastEntryHeader.CompressedSize = reader.ReadUInt32(); - _lastEntryHeader.UncompressedSize = reader.ReadUInt32(); + + // The DataDescriptor can be either 64bit or 32bit + var compressed_size = reader.ReadUInt32(); + var uncompressed_size = reader.ReadUInt32(); + + // Check if we have header or 64bit DataDescriptor + headerBytes = reader.ReadUInt32(); + bool test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50); + + long test_64bit = (long)uncompressed_size << 32 | (long)compressed_size; + if ( test_64bit == _lastEntryHeader.CompressedSize && test_header ) + { + _lastEntryHeader.UncompressedSize = (long)reader.ReadUInt32() << 32 | (long)headerBytes; + headerBytes = reader.ReadUInt32(); + } + else + { + _lastEntryHeader.UncompressedSize = uncompressed_size; + } + if (pos.HasValue) { _lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize; } } + else + { + headerBytes = reader.ReadUInt32(); + } + _lastEntryHeader = null; - uint headerBytes = reader.ReadUInt32(); header = ReadHeader(headerBytes, reader); if (header is null) { @@ -86,4 +109,4 @@ namespace SharpCompress.Common.Zip } } } -} \ No newline at end of file +} diff --git a/src/SharpCompress/IO/SourceStream.cs b/src/SharpCompress/IO/SourceStream.cs index 71918c81..22e44b22 100644 --- a/src/SharpCompress/IO/SourceStream.cs +++ b/src/SharpCompress/IO/SourceStream.cs @@ -143,9 +143,11 @@ namespace SharpCompress.IO if (!IsVolumes && count != 0 && Current.Position == Current.Length) { - _prevSize += Current.Length; + var length = Current.Length; + if (!SetStream(_stream + 1)) //will load next file if present break; + _prevSize += length; Current.Seek(0, SeekOrigin.Begin); } } diff --git a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs index 89cc4c13..65ae9326 100644 --- a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs @@ -401,8 +401,6 @@ namespace SharpCompress.Test.Zip } } - - [Fact] public void Zip_Uncompressed_Skip_All() { @@ -415,5 +413,26 @@ namespace SharpCompress.Test.Zip } } } + + [Fact] + public void Zip_Uncompressed_64bit() + { + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "64bitstream.zip.7z"); + using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) + { + var archive = Archives.ArchiveFactory.Open(stream); + var reader = archive.ExtractAllEntries(); + reader.MoveToNextEntry(); + var zipReader = ZipReader.Open(reader.OpenEntryStream()); + var x = 0; + while (zipReader.MoveToNextEntry()) + { + x++; + } + + Assert.Equal(4, x); + } + } + } } diff --git a/tests/TestArchives/Archives/64bitstream.zip.7z b/tests/TestArchives/Archives/64bitstream.zip.7z new file mode 100644 index 00000000..18b942c1 Binary files /dev/null and b/tests/TestArchives/Archives/64bitstream.zip.7z differ