static public bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header)
{
header = new ZipCentralDirectoryFileHeader();
if (reader.ReadUInt32() != SignatureConstant)
return false;
header.VersionMadeBySpecification = reader.ReadByte();
header.VersionMadeByCompatibility = reader.ReadByte();
header.VersionNeededToExtract = reader.ReadUInt16();
header.GeneralPurposeBitFlag = reader.ReadUInt16();
header.CompressionMethod = reader.ReadUInt16();
header.LastModified = reader.ReadUInt32();
header.Crc32 = reader.ReadUInt32();
uint compressedSizeSmall = reader.ReadUInt32();
uint uncompressedSizeSmall = reader.ReadUInt32();
header.FilenameLength = reader.ReadUInt16();
header.ExtraFieldLength = reader.ReadUInt16();
header.FileCommentLength = reader.ReadUInt16();
ushort diskNumberStartSmall = reader.ReadUInt16();
header.InternalFileAttributes = reader.ReadUInt16();
header.ExternalFileAttributes = reader.ReadUInt32();
uint relativeOffsetOfLocalHeaderSmall = reader.ReadUInt32();
header.Filename = reader.ReadBytes(header.FilenameLength);
bool uncompressedSizeInZip64 = uncompressedSizeSmall == ZipHelper.Mask32Bit;
bool compressedSizeInZip64 = compressedSizeSmall == ZipHelper.Mask32Bit;
bool relativeOffsetInZip64 = relativeOffsetOfLocalHeaderSmall == ZipHelper.Mask32Bit;
bool diskNumberStartInZip64 = diskNumberStartSmall == ZipHelper.Mask16Bit;
Zip64ExtraField zip64;
long endExtraFields = reader.BaseStream.Position + header.ExtraFieldLength;
using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, header.ExtraFieldLength))
{
if (saveExtraFieldsAndComments)
{
header.ExtraFields = ZipGenericExtraField.ParseExtraField(str);
zip64 = Zip64ExtraField.GetAndRemoveZip64Block(header.ExtraFields,
uncompressedSizeInZip64, compressedSizeInZip64,
relativeOffsetInZip64, diskNumberStartInZip64);
}
else
{
header.ExtraFields = null;
zip64 = Zip64ExtraField.GetJustZip64Block(str,
uncompressedSizeInZip64, compressedSizeInZip64,
relativeOffsetInZip64, diskNumberStartInZip64);
}
}
// There are zip files that have malformed ExtraField blocks in which GetJustZip64Block() silently bails out without reading all the way to the end
// of the ExtraField block. Thus we must force the stream's position to the proper place.
reader.BaseStream.AdvanceToPosition(endExtraFields);
if (saveExtraFieldsAndComments)
header.FileComment = reader.ReadBytes(header.FileCommentLength);
else
{
reader.BaseStream.Position += header.FileCommentLength;
header.FileComment = null;
}
header.UncompressedSize = zip64.UncompressedSize == null
? uncompressedSizeSmall
: zip64.UncompressedSize.Value;
header.CompressedSize = zip64.CompressedSize == null
? compressedSizeSmall
: zip64.CompressedSize.Value;
header.RelativeOffsetOfLocalHeader = zip64.LocalHeaderOffset == null
? relativeOffsetOfLocalHeaderSmall
: zip64.LocalHeaderOffset.Value;
header.DiskNumberStart = zip64.StartDiskNumber == null
? diskNumberStartSmall
: zip64.StartDiskNumber.Value;
return true;
}
}