Exemple #1
0
 internal override void Read(MarkingBinaryReader reader)
 {
     VolumeNumber                       = reader.ReadUInt16();
     FirstVolumeWithDirectory           = reader.ReadUInt16();
     TotalNumberOfEntriesInDisk         = reader.ReadUInt16();
     TotalNumberOfEntries               = reader.ReadUInt16();
     DirectorySize                      = reader.ReadUInt32();
     DirectoryStartOffsetRelativeToDisk = reader.ReadUInt32();
     CommentLength                      = reader.ReadUInt16();
     Comment = reader.ReadBytes(CommentLength);
 }
Exemple #2
0
        private static DateTime?ProcessExtendedTime(ushort extendedFlags, DateTime?time, MarkingBinaryReader reader, int i)
        {
            uint rmode = (uint)extendedFlags >> (3 - i) * 4;

            if ((rmode & 8) == 0)
            {
                return(null);
            }
            if (i != 0)
            {
                uint DosTime = reader.ReadUInt32();
                time = Utility.DosDateToDateTime(DosTime);
            }
            if ((rmode & 4) == 0)
            {
                time = time.Value.AddSeconds(1);
            }
            uint nanosecondHundreds = 0;
            int  count = (int)rmode & 3;

            for (int j = 0; j < count; j++)
            {
                byte b = reader.ReadByte();
                nanosecondHundreds |= (((uint)b) << ((j + 3 - count) * 8));
            }
            //10^-7 to 10^-3
            return(time.Value.AddMilliseconds(nanosecondHundreds * Math.Pow(10, -4)));
        }
Exemple #3
0
 protected override void ReadFromReader(MarkingBinaryReader reader)
 {
     Version     = reader.ReadByte();
     RecSectors  = reader.ReadUInt16();
     TotalBlocks = reader.ReadUInt32();
     Mark        = reader.ReadBytes(8);
 }
Exemple #4
0
        private static DateTime?ProcessExtendedTime(ushort extendedFlags, DateTime?time, MarkingBinaryReader reader, int i)
        {
            uint num = (uint)(extendedFlags >> ((3 - i) * 4));

            if ((num & 8) == 0)
            {
                return(null);
            }
            if (i != 0)
            {
                uint iTime = reader.ReadUInt32();
                time = new DateTime?(Utility.DosDateToDateTime(iTime));
            }
            if ((num & 4) == 0)
            {
                time = new DateTime?(time.Value.AddSeconds(1.0));
            }
            uint num3 = 0;
            int  num4 = ((int)num) & 3;

            for (int j = 0; j < num4; j++)
            {
                byte num6 = reader.ReadByte();
                num3 |= (uint)(num6 << (((j + 3) - num4) * 8));
            }
            return(new DateTime?(time.Value.AddMilliseconds(num3 * Math.Pow(10.0, -4.0))));
        }
        internal override void Read(MarkingBinaryReader reader)
        {
            Version           = reader.ReadUInt16();
            Flags             = reader.ReadUInt16();
            CompressionMethod = reader.ReadUInt16();
            LastModifiedTime  = reader.ReadUInt16();
            LastModifiedDate  = reader.ReadUInt16();
            Crc              = reader.ReadUInt32();
            CompressedSize   = reader.ReadUInt32();
            UncompressedSize = reader.ReadUInt32();
            ushort nameLength  = reader.ReadUInt16();
            ushort extraLength = reader.ReadUInt16();

            byte[] name = reader.ReadBytes(nameLength);
            Extra = reader.ReadBytes(extraLength);
            Name  = DefaultEncoding.GetString(name, 0, name.Length);
        }
        internal static IEnumerable <ZipHeader> ReadHeaderNonseekable(Stream stream)
        {
            while (true)
            {
                ZipHeader header = null;
                try
                {
                    MarkingBinaryReader reader = new MarkingBinaryReader(stream);

                    uint headerBytes = reader.ReadUInt32();
                    switch (headerBytes)
                    {
                    case ENTRY_HEADER_BYTES:
                    {
                        var entry = new LocalEntryHeader();
                        entry.Read(reader);
                        if (entry.CompressedSize > 0)
                        {
                            entry.PackedStream = new ReadOnlySubStream(stream, entry.CompressedSize, true);
                        }
                        header = entry;
                    }
                    break;

                    case DIRECTORY_START_HEADER_BYTES:
                    {
                        var entry = new DirectoryEntryHeader();
                        entry.Read(reader);
                        header = entry;
                    }
                    break;

                    case POST_DATA_DESCRIPTOR:
                    case DIGITAL_SIGNATURE:
                        break;

                    case DIRECTORY_END_HEADER_BYTES:
                    {
                        var entry = new DirectoryEndHeader();
                        entry.Read(reader);
                        header = entry;
                    }
                    break;

                    case ZIP64_END_OF_CENTRAL_DIRECTORY:
                    default:
                        break;
                    }
                }
                catch
                {
                    header = null;
                }
                yield return(header);
            }
        }
Exemple #7
0
 protected virtual void ReadFromReader(MarkingBinaryReader reader)
 {
     HeadCRC    = reader.ReadInt16();
     HeaderType = (HeaderType)(int)(reader.ReadByte() & 0xff);
     Flags      = reader.ReadInt16();
     HeaderSize = reader.ReadInt16();
     if (FlagUtility.HasFlag(Flags, LONG_BLOCK))
     {
         AdditionalSize = reader.ReadUInt32();
     }
 }
Exemple #8
0
 protected virtual void ReadFromReader(MarkingBinaryReader reader)
 {
     this.HeadCRC    = reader.ReadInt16();
     this.HeaderType = ((SharpCompress.Common.Rar.Headers.HeaderType)reader.ReadByte()) & ((SharpCompress.Common.Rar.Headers.HeaderType) 0xff);
     this.Flags      = reader.ReadInt16();
     this.HeaderSize = reader.ReadInt16();
     if (FlagUtility.HasFlag((short)this.Flags, (short)-32768))
     {
         this.AdditionalSize = reader.ReadUInt32();
     }
 }
Exemple #9
0
 private static DateTime ReadExtendedTimeV5(MarkingBinaryReader reader, bool isWindowsTime)
 {
     if (isWindowsTime)
     {
         return(DateTime.FromFileTime(reader.ReadInt64()));
     }
     else
     {
         return(Utility.UnixTimeToDateTime(reader.ReadUInt32()));
     }
 }
Exemple #10
0
        internal override void Read(MarkingBinaryReader reader)
        {
            Version = reader.ReadUInt16();
            VersionNeededToExtract = reader.ReadUInt16();
            Flags             = reader.ReadUInt16();
            CompressionMethod = reader.ReadUInt16();
            LastModifiedTime  = reader.ReadUInt16();
            LastModifiedDate  = reader.ReadUInt16();
            Crc              = reader.ReadUInt32();
            CompressedSize   = reader.ReadUInt32();
            UncompressedSize = reader.ReadUInt32();
            ushort nameLength    = reader.ReadUInt16();
            ushort extraLength   = reader.ReadUInt16();
            ushort commentLength = reader.ReadUInt16();

            DiskNumberStart             = reader.ReadUInt16();
            InternalFileAttributes      = reader.ReadUInt16();
            ExternalFileAttributes      = reader.ReadUInt32();
            RelativeOffsetOfEntryHeader = reader.ReadUInt32();

            Name    = DefaultEncoding.GetString(reader.ReadBytes(nameLength));
            Extra   = reader.ReadBytes(extraLength);
            Comment = reader.ReadBytes(commentLength);
        }
Exemple #11
0
        protected override void ReadFromReader(MarkingBinaryReader reader)
        {
            uint lowUncompressedSize = reader.ReadUInt32();

            HostOS = (HostOS)(int)reader.ReadByte();

            FileCRC = reader.ReadUInt32();

            FileLastModifiedTime = Utility.DosDateToDateTime(reader.ReadInt32());

            RarVersion    = reader.ReadByte();
            PackingMethod = reader.ReadByte();

            short nameSize = reader.ReadInt16();

            FileAttributes = reader.ReadInt32();

            uint highCompressedSize    = 0;
            uint highUncompressedkSize = 0;

            if (FileFlags.HasFlag(FileFlags.LARGE))
            {
                highCompressedSize    = reader.ReadUInt32();
                highUncompressedkSize = reader.ReadUInt32();
            }
            else
            {
                if (lowUncompressedSize == 0xffffffff)
                {
                    lowUncompressedSize   = 0xffffffff;
                    highUncompressedkSize = int.MaxValue;
                }
            }
            CompressedSize   = UInt32To64(highCompressedSize, AdditionalSize);
            UncompressedSize = UInt32To64(highUncompressedkSize, lowUncompressedSize);

            nameSize = nameSize > 4 * 1024 ? (short)(4 * 1024) : nameSize;

            byte[] fileNameBytes = reader.ReadBytes(nameSize);

            switch (HeaderType)
            {
            case HeaderType.FileHeader:
            {
                if (FileFlags.HasFlag(FileFlags.UNICODE))
                {
                    int length = 0;
                    while (length < fileNameBytes.Length &&
                           fileNameBytes[length] != 0)
                    {
                        length++;
                    }
                    if (length != nameSize)
                    {
                        length++;
                        FileName = FileNameDecoder.Decode(fileNameBytes, length);
                    }
                    else
                    {
                        FileName = DecodeDefault(fileNameBytes);
                    }
                }
                else
                {
                    FileName = DecodeDefault(fileNameBytes);
                }
                FileName = ConvertPath(FileName, HostOS);
            }
            break;

            case HeaderType.NewSubHeader:
            {
                int datasize = HeaderSize - NEWLHD_SIZE - nameSize;
                if (FileFlags.HasFlag(FileFlags.SALT))
                {
                    datasize -= SALT_SIZE;
                }
                if (datasize > 0)
                {
                    SubData = reader.ReadBytes(datasize);
                }

                if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
                {
                    RecoverySectors = SubData[8] + (SubData[9] << 8)
                                      + (SubData[10] << 16) + (SubData[11] << 24);
                }
            }
            break;
            }

            if (FileFlags.HasFlag(FileFlags.SALT))
            {
                Salt = reader.ReadBytes(SALT_SIZE);
            }
            if (FileFlags.HasFlag(FileFlags.EXTTIME))
            {
                ushort extendedFlags = reader.ReadUInt16();
                FileLastModifiedTime = ProcessExtendedTime(extendedFlags, FileLastModifiedTime, reader, 0);
                FileCreatedTime      = ProcessExtendedTime(extendedFlags, null, reader, 1);
                FileLastAccessedTime = ProcessExtendedTime(extendedFlags, null, reader, 2);
                FileArchivedTime     = ProcessExtendedTime(extendedFlags, null, reader, 3);
            }
        }
Exemple #12
0
        protected override void ReadFromReader(MarkingBinaryReader reader)
        {
            uint y = reader.ReadUInt32();

            this.HostOS  = (SharpCompress.Common.Rar.Headers.HostOS)reader.ReadByte();
            this.FileCRC = reader.ReadUInt32();
            this.FileLastModifiedTime = new DateTime?(Utility.DosDateToDateTime(reader.ReadInt32()));
            this.RarVersion           = reader.ReadByte();
            this.PackingMethod        = reader.ReadByte();
            short count = reader.ReadInt16();

            this.FileAttributes = reader.ReadInt32();
            uint x    = 0;
            uint num4 = 0;

            if (this.FileFlags_HasFlag(SharpCompress.Common.Rar.Headers.FileFlags.LARGE))
            {
                x    = reader.ReadUInt32();
                num4 = reader.ReadUInt32();
            }
            else if (y == uint.MaxValue)
            {
                y    = uint.MaxValue;
                num4 = 0x7fffffff;
            }
            this.CompressedSize   = this.UInt32To64(x, base.AdditionalSize);
            this.UncompressedSize = this.UInt32To64(num4, y);
            count = (count > 0x1000) ? ((short)0x1000) : count;
            byte[] name = reader.ReadBytes(count);
            switch (base.HeaderType)
            {
            case HeaderType.FileHeader:
                if (this.FileFlags_HasFlag(SharpCompress.Common.Rar.Headers.FileFlags.UNICODE))
                {
                    int index = 0;
                    while ((index < name.Length) && (name[index] != 0))
                    {
                        index++;
                    }
                    if (index != count)
                    {
                        index++;
                        this.FileName = FileNameDecoder.Decode(name, index);
                    }
                    else
                    {
                        this.FileName = this.DecodeDefault(name);
                    }
                }
                else
                {
                    this.FileName = this.DecodeDefault(name);
                }
                this.FileName = ConvertPath(this.FileName, this.HostOS);
                break;

            case HeaderType.NewSubHeader:
            {
                int num6 = (base.HeaderSize - 0x20) - count;
                if (this.FileFlags_HasFlag(SharpCompress.Common.Rar.Headers.FileFlags.SALT))
                {
                    num6 -= 8;
                }
                if (num6 > 0)
                {
                    this.SubData = reader.ReadBytes(num6);
                }
                if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(name))
                {
                    this.RecoverySectors = ((this.SubData[8] + (this.SubData[9] << 8)) + (this.SubData[10] << 0x10)) + (this.SubData[11] << 0x18);
                }
                break;
            }
            }
            if (this.FileFlags_HasFlag(SharpCompress.Common.Rar.Headers.FileFlags.SALT))
            {
                this.Salt = reader.ReadBytes(8);
            }
            if (this.FileFlags_HasFlag(SharpCompress.Common.Rar.Headers.FileFlags.EXTTIME) && ((base.ReadBytes + reader.CurrentReadByteCount) <= (base.HeaderSize - 2)))
            {
                ushort extendedFlags = reader.ReadUInt16();
                this.FileLastModifiedTime = ProcessExtendedTime(extendedFlags, this.FileLastModifiedTime, reader, 0);
                DateTime?time = null;
                this.FileCreatedTime = ProcessExtendedTime(extendedFlags, time, reader, 1);
                time = null;
                this.FileLastAccessedTime = ProcessExtendedTime(extendedFlags, time, reader, 2);
                this.FileArchivedTime     = ProcessExtendedTime(extendedFlags, null, reader, 3);
            }
        }
Exemple #13
0
        private void ReadFromReaderV5(MarkingBinaryReader reader)
        {
            Flags = reader.ReadRarVIntUInt16();

            var lvalue = checked ((long)reader.ReadRarVInt());

            // long.MaxValue causes the unpack code to finish when the input stream is exhausted
            UncompressedSize = HasFlag(FileFlagsV5.UNPACKED_SIZE_UNKNOWN) ? long.MaxValue : lvalue;

            FileAttributes = reader.ReadRarVIntUInt32();

            if (HasFlag(FileFlagsV5.HAS_MOD_TIME))
            {
                FileLastModifiedTime = Utility.UnixTimeToDateTime(reader.ReadUInt32());
            }

            if (HasFlag(FileFlagsV5.HAS_CRC32))
            {
                FileCrc = reader.ReadUInt32();
            }

            var compressionInfo = reader.ReadRarVIntUInt16();

            // Lower 6 bits (0x003f mask) contain the version of compression algorithm, resulting in possible 0 - 63 values. Current version is 0.
            // "+ 50" to not mix with old RAR format algorithms. For example,
            // we may need to use the compression algorithm 15 in the future,
            // but it was already used in RAR 1.5 and Unpack needs to distinguish
            // them.
            CompressionAlgorithm = (byte)((compressionInfo & 0x3f) + 50);

            // 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files.
            // It can be set only for file headers and is never set for service headers.
            IsSolid = (compressionInfo & 0x40) == 0x40;

            // Bits 8 - 10 (0x0380 mask) define the compression method. Currently only values 0 - 5 are used. 0 means no compression.
            CompressionMethod = (byte)((compressionInfo >> 7) & 0x7);

            // Bits 11 - 14 (0x3c00) define the minimum size of dictionary size required to extract data. Value 0 means 128 KB, 1 - 256 KB, ..., 14 - 2048 MB, 15 - 4096 MB.
            WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((compressionInfo >> 10) & 0xf);

            HostOs = reader.ReadRarVIntByte();

            var nameSize = reader.ReadRarVIntUInt16();

            // Variable length field containing Name length bytes in UTF-8 format without trailing zero.
            // For file header this is a name of archived file. Forward slash character is used as the path separator both for Unix and Windows names.
            // Backslashes are treated as a part of name for Unix names and as invalid character for Windows file names. Type of name is defined by Host OS field.
            //
            // TODO: not sure if anything needs to be done to handle the following:
            // If Unix file name contains any high ASCII characters which cannot be correctly converted to Unicode and UTF-8
            // we map such characters to to 0xE080 - 0xE0FF private use Unicode area and insert 0xFFFE Unicode non-character
            // to resulting string to indicate that it contains mapped characters, which need to be converted back when extracting.
            // Concrete position of 0xFFFE is not defined, we need to search the entire string for it. Such mapped names are not
            // portable and can be correctly unpacked only on the same system where they were created.
            //
            // For service header this field contains a name of service header. Now the following names are used:
            // CMT	Archive comment
            // QO	Archive quick open data
            // ACL	NTFS file permissions
            // STM	NTFS alternate data stream
            // RR	Recovery record
            var b = reader.ReadBytes(nameSize);

            FileName = ConvertPathV5(Encoding.UTF8.GetString(b, 0, b.Length));

            // extra size seems to be redudant since we know the total header size
            if (ExtraSize != RemainingHeaderBytes(reader))
            {
                throw new InvalidFormatException("rar5 header size / extra size inconsistency");
            }

            isEncryptedRar5 = false;

            while (RemainingHeaderBytes(reader) > 0)
            {
                var size = reader.ReadRarVIntUInt16();
                int n    = RemainingHeaderBytes(reader);
                var type = reader.ReadRarVIntUInt16();
                switch (type)
                {
                //TODO
                case 1:     // file encryption
                {
                    isEncryptedRar5 = true;

                    //var version = reader.ReadRarVIntByte();
                    //if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version);
                }
                break;

                //                    case 2: // file hash
                //                        {
                //
                //                        }
                //                        break;
                case 3:     // file time
                {
                    ushort flags         = reader.ReadRarVIntUInt16();
                    var    isWindowsTime = (flags & 1) == 0;
                    if ((flags & 0x2) == 0x2)
                    {
                        FileLastModifiedTime = ReadExtendedTimeV5(reader, isWindowsTime);
                    }
                    if ((flags & 0x4) == 0x4)
                    {
                        FileCreatedTime = ReadExtendedTimeV5(reader, isWindowsTime);
                    }
                    if ((flags & 0x8) == 0x8)
                    {
                        FileLastAccessedTime = ReadExtendedTimeV5(reader, isWindowsTime);
                    }
                }
                break;
//TODO
//                    case 4: // file version
//                        {
//
//                        }
//                        break;
//                    case 5: // file system redirection
//                        {
//
//                        }
//                        break;
//                    case 6: // unix owner
//                        {
//
//                        }
//                        break;
//                    case 7: // service data
//                        {
//
//                        }
//                        break;

                default:
                    // skip unknown record types to allow new record types to be added in the future
                    break;
                }
                // drain any trailing bytes of extra record
                int did   = n - RemainingHeaderBytes(reader);
                int drain = size - did;
                if (drain > 0)
                {
                    reader.ReadBytes(drain);
                }
            }

            if (AdditionalDataSize != 0)
            {
                CompressedSize = AdditionalDataSize;
            }
        }
Exemple #14
0
        private void ReadFromReaderV4(MarkingBinaryReader reader)
        {
            Flags      = HeaderFlags;
            IsSolid    = HasFlag(FileFlagsV4.SOLID);
            WindowSize = IsDirectory ? 0U : ((size_t)0x10000) << ((Flags & FileFlagsV4.WINDOW_MASK) >> 5);

            uint lowUncompressedSize = reader.ReadUInt32();

            HostOs = reader.ReadByte();

            FileCrc = reader.ReadUInt32();

            FileLastModifiedTime = Utility.DosDateToDateTime(reader.ReadUInt32());

            CompressionAlgorithm = reader.ReadByte();
            CompressionMethod    = (byte)(reader.ReadByte() - 0x30);

            short nameSize = reader.ReadInt16();

            FileAttributes = reader.ReadUInt32();

            uint highCompressedSize    = 0;
            uint highUncompressedkSize = 0;

            if (HasFlag(FileFlagsV4.LARGE))
            {
                highCompressedSize    = reader.ReadUInt32();
                highUncompressedkSize = reader.ReadUInt32();
            }
            else
            {
                if (lowUncompressedSize == 0xffffffff)
                {
                    lowUncompressedSize   = 0xffffffff;
                    highUncompressedkSize = int.MaxValue;
                }
            }
            CompressedSize   = UInt32To64(highCompressedSize, checked ((uint)AdditionalDataSize));
            UncompressedSize = UInt32To64(highUncompressedkSize, lowUncompressedSize);

            nameSize = nameSize > 4 * 1024 ? (short)(4 * 1024) : nameSize;

            byte[] fileNameBytes = reader.ReadBytes(nameSize);

            const int saltSize   = 8;
            const int newLhdSize = 32;

            switch (HeaderCode)
            {
            case HeaderCodeV.RAR4_FILE_HEADER:
            {
                if (HasFlag(FileFlagsV4.UNICODE))
                {
                    int length = 0;
                    while (length < fileNameBytes.Length &&
                           fileNameBytes[length] != 0)
                    {
                        length++;
                    }
                    if (length != nameSize)
                    {
                        length++;
                        FileName = FileNameDecoder.Decode(fileNameBytes, length);
                    }
                    else
                    {
                        FileName = ArchiveEncoding.Decode(fileNameBytes);
                    }
                }
                else
                {
                    FileName = ArchiveEncoding.Decode(fileNameBytes);
                }
                FileName = ConvertPathV4(FileName);
            }
            break;

            case HeaderCodeV.RAR4_NEW_SUB_HEADER:
            {
                int datasize = HeaderSize - newLhdSize - nameSize;
                if (HasFlag(FileFlagsV4.SALT))
                {
                    datasize -= saltSize;
                }
                if (datasize > 0)
                {
                    SubData = reader.ReadBytes(datasize);
                }

                if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
                {
                    RecoverySectors = SubData[8] + (SubData[9] << 8)
                                      + (SubData[10] << 16) + (SubData[11] << 24);
                }
            }
            break;
            }

            if (HasFlag(FileFlagsV4.SALT))
            {
                R4Salt = reader.ReadBytes(saltSize);
            }
            if (HasFlag(FileFlagsV4.EXT_TIME))
            {
                // verify that the end of the header hasn't been reached before reading the Extended Time.
                //  some tools incorrectly omit Extended Time despite specifying FileFlags.EXTTIME, which most parsers tolerate.
                if (RemainingHeaderBytes(reader) >= 2)
                {
                    ushort extendedFlags = reader.ReadUInt16();
                    FileLastModifiedTime = ProcessExtendedTimeV4(extendedFlags, FileLastModifiedTime, reader, 0);
                    FileCreatedTime      = ProcessExtendedTimeV4(extendedFlags, null, reader, 1);
                    FileLastAccessedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 2);
                    FileArchivedTime     = ProcessExtendedTimeV4(extendedFlags, null, reader, 3);
                }
            }
        }
Exemple #15
0
        protected override void ReadFromReader(MarkingBinaryReader reader)
        {
            FileHeaderFlags = (FileFlags)reader.ReadVInt();
            UnpackedSize    = reader.ReadVInt();
            Attributes      = reader.ReadVInt();
            if (FileHeaderFlags.HasFlag(FileFlags.TimeFieldIsPresent))
            {
                MTime = reader.ReadUInt32();
                FileLastModifiedTime = Utility.UnixTimeToDateTime(MTime);
            }
            if (FileHeaderFlags.HasFlag(FileFlags.CRC32IsPresent))
            {
                DataCRC32 = reader.ReadUInt32();
            }
            CompressionInformation = reader.ReadVInt();
            HostOS = (HostOS)reader.ReadVInt();

            var nameSize = (int)reader.ReadVInt();

            Name = Encoding.UTF8.GetString(reader.ReadBytes(nameSize));

            uint highCompressedSize    = 0;
            uint highUncompressedkSize = 0;

            if (FileFlags.HasFlag(FileFlags.LARGE))
            {
                highCompressedSize    = reader.ReadUInt32();
                highUncompressedkSize = reader.ReadUInt32();
            }
            else
            {
                if (lowUncompressedSize == 0xffffffff)
                {
                    lowUncompressedSize   = 0xffffffff;
                    highUncompressedkSize = int.MaxValue;
                }
            }
            CompressedSize   = UInt32To64(highCompressedSize, AdditionalSize);
            UncompressedSize = UInt32To64(highUncompressedkSize, lowUncompressedSize);

            nameSize = nameSize > 4 * 1024 ? (short)(4 * 1024) : nameSize;

            byte[] fileNameBytes = reader.ReadBytes(nameSize);

            switch (HeaderType)
            {
            case HeaderType.FileHeader:
            {
                if (FileFlags.HasFlag(FileFlags.UNICODE))
                {
                    int length = 0;
                    while (length < fileNameBytes.Length &&
                           fileNameBytes[length] != 0)
                    {
                        length++;
                    }
                    if (length != nameSize)
                    {
                        length++;
                        FileName = FileNameDecoder.Decode(fileNameBytes, length);
                    }
                    else
                    {
                        FileName = ArchiveEncoding.Decode(fileNameBytes);
                    }
                }
                else
                {
                    FileName = ArchiveEncoding.Decode(fileNameBytes);
                }
                FileName = ConvertPath(FileName, HostOS);
            }
            break;

            case HeaderType.NewSubHeader:
            {
                int datasize = HeaderSize - NEWLHD_SIZE - nameSize;
                if (FileFlags.HasFlag(FileFlags.SALT))
                {
                    datasize -= SALT_SIZE;
                }
                if (datasize > 0)
                {
                    SubData = reader.ReadBytes(datasize);
                }

                if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
                {
                    RecoverySectors = SubData[8] + (SubData[9] << 8)
                                      + (SubData[10] << 16) + (SubData[11] << 24);
                }
            }
            break;
            }

            if (FileFlags.HasFlag(FileFlags.SALT))
            {
                Salt = reader.ReadBytes(SALT_SIZE);
            }
            if (FileFlags.HasFlag(FileFlags.EXTTIME))
            {
                // verify that the end of the header hasn't been reached before reading the Extended Time.
                //  some tools incorrectly omit Extended Time despite specifying FileFlags.EXTTIME, which most parsers tolerate.
                if (ReadBytes + reader.CurrentReadByteCount <= HeaderSize - 2)
                {
                    ushort extendedFlags = reader.ReadUInt16();
                    FileLastModifiedTime = ProcessExtendedTime(extendedFlags, FileLastModifiedTime, reader, 0);
                    FileCreatedTime      = ProcessExtendedTime(extendedFlags, null, reader, 1);
                    FileLastAccessedTime = ProcessExtendedTime(extendedFlags, null, reader, 2);
                    FileArchivedTime     = ProcessExtendedTime(extendedFlags, null, reader, 3);
                }
            }
        }