123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- using System;
- using System.Text;
- using SharpCompress.Converters;
- namespace SharpCompress.Common.Zip.Headers
- {
- internal enum ExtraDataType : ushort
- {
- WinZipAes = 0x9901,
- NotImplementedExtraData = 0xFFFF,
- // Third Party Mappings
- // -Info-ZIP Unicode Path Extra Field
- UnicodePathExtraField = 0x7075,
- Zip64ExtendedInformationExtraField = 0x0001
- }
- internal class ExtraData
- {
- internal ExtraDataType Type { get; set; }
- internal ushort Length { get; set; }
- internal byte[] DataBytes { get; set; }
- }
- internal class ExtraUnicodePathExtraField : ExtraData
- {
- internal byte Version => DataBytes[0];
- internal byte[] NameCrc32
- {
- get
- {
- var crc = new byte[4];
- Buffer.BlockCopy(DataBytes, 1, crc, 0, 4);
- return crc;
- }
- }
- internal string UnicodeName
- {
- get
- {
- // PathNamelength = dataLength - Version(1 byte) - NameCRC32(4 bytes)
- var length = Length - 5;
- var nameStr = Encoding.UTF8.GetString(DataBytes, 5, length);
- return nameStr;
- }
- }
- }
- internal class Zip64ExtendedInformationExtraField : ExtraData
- {
- public Zip64ExtendedInformationExtraField(ExtraDataType type, ushort length, byte[] dataBytes)
- {
- Type = type;
- Length = length;
- DataBytes = dataBytes;
- Process();
- }
- //From the spec values are only in the extradata if the standard
- //value is set to 0xFFFF, but if one of the sizes are present, both are.
- //Hence if length == 4 volume only
- // if length == 8 offset only
- // if length == 12 offset + volume
- // if length == 16 sizes only
- // if length == 20 sizes + volume
- // if length == 24 sizes + offset
- // if length == 28 everything.
- //It is unclear how many of these are used in the wild.
- private void Process()
- {
- switch (DataBytes.Length)
- {
- case 4:
- VolumeNumber = DataConverter.LittleEndian.GetUInt32(DataBytes, 0);
- return;
- case 8:
- RelativeOffsetOfEntryHeader = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- return;
- case 12:
- RelativeOffsetOfEntryHeader = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- VolumeNumber = DataConverter.LittleEndian.GetUInt32(DataBytes, 8);
- return;
- case 16:
- UncompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- CompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 8);
- return;
- case 20:
- UncompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- CompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 8);
- VolumeNumber = DataConverter.LittleEndian.GetUInt32(DataBytes, 16);
- return;
- case 24:
- UncompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- CompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 8);
- RelativeOffsetOfEntryHeader = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 16);
- return;
- case 28:
- UncompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 0);
- CompressedSize = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 8);
- RelativeOffsetOfEntryHeader = (long)DataConverter.LittleEndian.GetUInt64(DataBytes, 16);
- VolumeNumber = DataConverter.LittleEndian.GetUInt32(DataBytes, 24);
- return;
- default:
- throw new ArchiveException("Unexpected size of of Zip64 extended information extra field");
- }
- }
- public long UncompressedSize { get; private set; }
- public long CompressedSize { get; private set; }
- public long RelativeOffsetOfEntryHeader { get; private set; }
- public uint VolumeNumber { get; private set; }
- }
- internal static class LocalEntryHeaderExtraFactory
- {
- internal static ExtraData Create(ExtraDataType type, ushort length, byte[] extraData)
- {
- switch (type)
- {
- case ExtraDataType.UnicodePathExtraField:
- return new ExtraUnicodePathExtraField
- {
- Type = type,
- Length = length,
- DataBytes = extraData
- };
- case ExtraDataType.Zip64ExtendedInformationExtraField:
- return new Zip64ExtendedInformationExtraField
- (
- type,
- length,
- extraData
- );
- default:
- return new ExtraData
- {
- Type = type,
- Length = length,
- DataBytes = extraData
- };
- }
- }
- }
- }
|