2015-12-30 11:19:42 +00:00
|
|
|
|
using System.Collections.Generic;
|
2021-02-08 10:17:34 +00:00
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
using System.Threading;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
using SharpCompress.Common.Zip.Headers;
|
|
|
|
|
|
using SharpCompress.IO;
|
|
|
|
|
|
|
|
|
|
|
|
namespace SharpCompress.Common.Zip
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class StreamingZipHeaderFactory : ZipHeaderFactory
|
|
|
|
|
|
{
|
2020-05-23 16:27:55 -07:00
|
|
|
|
internal StreamingZipHeaderFactory(string? password, ArchiveEncoding archiveEncoding)
|
2017-07-17 10:53:20 -04:00
|
|
|
|
: base(StreamingMode.Streaming, password, archiveEncoding)
|
2015-12-30 11:19:42 +00:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-08 11:18:57 +00:00
|
|
|
|
internal async IAsyncEnumerable<ZipHeader> ReadStreamHeader(RewindableStream rewindableStream, [EnumeratorCancellation] CancellationToken cancellationToken)
|
2015-12-30 11:19:42 +00:00
|
|
|
|
{
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
2020-05-23 16:27:55 -07:00
|
|
|
|
ZipHeader? header;
|
2018-05-06 08:59:00 +01:00
|
|
|
|
if (_lastEntryHeader != null &&
|
|
|
|
|
|
(FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) || _lastEntryHeader.IsZip64))
|
2015-12-30 11:19:42 +00:00
|
|
|
|
{
|
2021-02-08 10:17:34 +00:00
|
|
|
|
await ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(rewindableStream, cancellationToken);
|
2016-08-12 11:56:49 +01:00
|
|
|
|
long? pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null;
|
2021-02-08 11:18:57 +00:00
|
|
|
|
uint crc = await rewindableStream.ReadUInt32(cancellationToken);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
if (crc == POST_DATA_DESCRIPTOR)
|
|
|
|
|
|
{
|
2021-02-08 11:18:57 +00:00
|
|
|
|
crc = await rewindableStream.ReadUInt32(cancellationToken);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
}
|
2018-05-06 08:59:00 +01:00
|
|
|
|
_lastEntryHeader.Crc = crc;
|
2021-02-08 11:18:57 +00:00
|
|
|
|
_lastEntryHeader.CompressedSize = await rewindableStream.ReadUInt32(cancellationToken);
|
|
|
|
|
|
_lastEntryHeader.UncompressedSize = await rewindableStream.ReadUInt32(cancellationToken);
|
2016-08-12 11:56:49 +01:00
|
|
|
|
if (pos.HasValue)
|
|
|
|
|
|
{
|
2018-05-06 08:59:00 +01:00
|
|
|
|
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;
|
2016-08-12 11:56:49 +01:00
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
}
|
2018-05-06 08:59:00 +01:00
|
|
|
|
_lastEntryHeader = null;
|
2021-02-08 11:18:57 +00:00
|
|
|
|
uint headerBytes = await rewindableStream.ReadUInt32(cancellationToken);
|
|
|
|
|
|
header = await ReadHeader(headerBytes, rewindableStream, cancellationToken);
|
2021-01-09 10:34:49 +00:00
|
|
|
|
if (header is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
yield break;
|
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
|
|
|
|
|
|
//entry could be zero bytes so we need to know that.
|
|
|
|
|
|
if (header.ZipHeaderType == ZipHeaderType.LocalEntry)
|
|
|
|
|
|
{
|
2020-01-16 22:08:48 +01:00
|
|
|
|
var local_header = ((LocalEntryHeader)header);
|
|
|
|
|
|
|
|
|
|
|
|
// If we have CompressedSize, there is data to be read
|
2021-01-09 13:33:34 +00:00
|
|
|
|
if (local_header.CompressedSize > 0)
|
2020-01-16 22:08:48 +01:00
|
|
|
|
{
|
|
|
|
|
|
header.HasData = true;
|
|
|
|
|
|
} // Check if zip is streaming ( Length is 0 and is declared in PostDataDescriptor )
|
2021-01-09 13:33:34 +00:00
|
|
|
|
else if (local_header.Flags.HasFlag(HeaderFlags.UsePostDataDescriptor))
|
2020-01-16 22:08:48 +01:00
|
|
|
|
{
|
|
|
|
|
|
bool isRecording = rewindableStream.IsRecording;
|
|
|
|
|
|
if (!isRecording)
|
|
|
|
|
|
{
|
|
|
|
|
|
rewindableStream.StartRecording();
|
|
|
|
|
|
}
|
2021-02-08 11:18:57 +00:00
|
|
|
|
uint nextHeaderBytes = await rewindableStream.ReadUInt32(cancellationToken);
|
2020-01-16 22:08:48 +01:00
|
|
|
|
|
|
|
|
|
|
// Check if next data is PostDataDescriptor, streamed file with 0 length
|
2021-02-08 11:18:57 +00:00
|
|
|
|
header.HasData = nextHeaderBytes != POST_DATA_DESCRIPTOR;
|
2020-01-16 22:08:48 +01:00
|
|
|
|
rewindableStream.Rewind(!isRecording);
|
|
|
|
|
|
}
|
|
|
|
|
|
else // We are not streaming and compressed size is 0, we have no data
|
2015-12-30 11:19:42 +00:00
|
|
|
|
{
|
2020-01-16 22:08:48 +01:00
|
|
|
|
header.HasData = false;
|
2015-12-30 11:19:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
yield return header;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2013-04-28 12:32:55 +01:00
|
|
|
|
}
|