예제 #1
0
        internal ZipReturn LocalFileHeaderReadQuick(Stream zipFs)
        {
            try
            {
                using BinaryReader br = new(zipFs, Encoding.UTF8, true);
                SetStatus(LocalFileStatus.TrrntZip);

                zipFs.Position = (long)RelativeOffsetOfLocalHeader;
                uint thisSignature = br.ReadUInt32();
                if (thisSignature != LocalFileHeaderSignature)
                {
                    return(ZipReturn.ZipLocalFileHeaderError);
                }

                br.ReadUInt16(); // version needed to extract
                GeneralPurposeBitFlag = br.ReadUInt16();
                if ((GeneralPurposeBitFlag & 8) == 8)
                {
                    return(ZipReturn.ZipCannotFastOpen);
                }

                _compressionMethod = br.ReadUInt16();

                ushort lastModFileTime = br.ReadUInt16();
                ushort lastModFileDate = br.ReadUInt16();
                HeaderLastModified = CompressUtils.UtcTicksFromDosDateTime(lastModFileDate, lastModFileTime);

                CRC              = ReadCRC(br);
                _compressedSize  = br.ReadUInt32();
                UncompressedSize = br.ReadUInt32();

                ushort fileNameLength   = br.ReadUInt16();
                ushort extraFieldLength = br.ReadUInt16();

                byte[] bFileName = br.ReadBytes(fileNameLength);

                Filename = (GeneralPurposeBitFlag & (1 << 11)) == 0
                    ? CompressUtils.GetString(bFileName)
                    : Encoding.UTF8.GetString(bFileName, 0, fileNameLength);

                SetStatus(LocalFileStatus.Zip64, false);
                if (extraFieldLength > 0)
                {
                    byte[] extraField = br.ReadBytes(extraFieldLength);

                    ulong     LocalHeader = 0;
                    ZipReturn zr          = ZipExtraField.ReadExtraField(extraField, bFileName, this, ref _compressedSize, ref LocalHeader, false);
                    if (zr != ZipReturn.ZipGood)
                    {
                        return(zr);
                    }
                }

                if (CompressUtils.IsCodePage437(Filename) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
                {
                    SetStatus(LocalFileStatus.TrrntZip, false);
                }

                _dataLocation = (ulong)zipFs.Position;

                return(ZipReturn.ZipGood);
            }
            catch
            {
                return(ZipReturn.ZipLocalFileHeaderError);
            }
        }
예제 #2
0
        internal ZipReturn CentralDirectoryRead(Stream zipFs, ulong offset)
        {
            try
            {
                using BinaryReader br = new(zipFs, Encoding.UTF8, true);
                uint thisSignature = br.ReadUInt32();
                if (thisSignature != CentralDirectoryHeaderSignature)
                {
                    return(ZipReturn.ZipCentralDirError);
                }

                br.ReadUInt16(); // Version Made By

                br.ReadUInt16(); // Version Needed To Extract


                GeneralPurposeBitFlag = br.ReadUInt16();
                _compressionMethod    = br.ReadUInt16();

                ushort lastModFileTime = br.ReadUInt16();
                ushort lastModFileDate = br.ReadUInt16();
                HeaderLastModified = CompressUtils.UtcTicksFromDosDateTime(lastModFileDate, lastModFileTime);

                CRC = ReadCRC(br);

                _compressedSize  = br.ReadUInt32();
                UncompressedSize = br.ReadUInt32();

                ushort fileNameLength    = br.ReadUInt16();
                ushort extraFieldLength  = br.ReadUInt16();
                ushort fileCommentLength = br.ReadUInt16();

                br.ReadUInt16(); // diskNumberStart
                br.ReadUInt16(); // internalFileAttributes
                br.ReadUInt32(); // externalFileAttributes

                RelativeOffsetOfLocalHeader = br.ReadUInt32();


                byte[] bFileName = br.ReadBytes(fileNameLength);
                Filename = (GeneralPurposeBitFlag & (1 << 11)) == 0
                    ? CompressUtils.GetString(bFileName)
                    : Encoding.UTF8.GetString(bFileName, 0, fileNameLength);

                if (extraFieldLength > 0)
                {
                    byte[] extraField = br.ReadBytes(extraFieldLength);

                    ZipReturn zr = ZipExtraField.ReadExtraField(extraField, bFileName, this, ref _compressedSize, ref RelativeOffsetOfLocalHeader, true);
                    if (zr != ZipReturn.ZipGood)
                    {
                        return(zr);
                    }
                }

                RelativeOffsetOfLocalHeader += offset;

                if (CompressUtils.IsCodePage437(Filename) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
                {
                    SetStatus(LocalFileStatus.TrrntZip, false);
                }

                if (fileCommentLength > 0)
                {
                    byte[] fileComment = br.ReadBytes(fileCommentLength);
                }

                if (Filename.Length > 0)
                {
                    char lastChar = Filename[Filename.Length - 1];
                    IsDirectory = (lastChar == '/' || lastChar == '\\');
                    if (IsDirectory && UncompressedSize > 0)
                    {
                        SetStatus(LocalFileStatus.DirectoryLengthError);
                    }
                }

                /*
                 * 4.4.5 compression method: (2 bytes)
                 *
                 * 0 - (Supported) The file is stored (no compression)
                 * 1 - (Supported) The file is Shrunk
                 * 2 - (Supported) The file is Reduced with compression factor 1
                 * 3 - (Supported) The file is Reduced with compression factor 2
                 * 4 - (Supported) The file is Reduced with compression factor 3
                 * 5 - (Supported) The file is Reduced with compression factor 4
                 * 6 - (Supported) The file is Imploded
                 * 7 - Reserved for Tokenizing compression algorithm
                 * 8 - (Supported) The file is Deflated
                 * 9 - (Supported) Enhanced Deflating using Deflate64(tm)
                 * 10 - PKWARE Data Compression Library Imploding (old IBM TERSE)
                 * 11 - Reserved by PKWARE
                 * 12 - (Supported) File is compressed using BZIP2 algorithm
                 * 13 - Reserved by PKWARE
                 * 14 - (Supported) LZMA
                 * 15 - Reserved by PKWARE
                 * 16 - IBM z/OS CMPSC Compression
                 * 17 - Reserved by PKWARE
                 * 18 - File is compressed using IBM TERSE (new)
                 * 19 - IBM LZ77 z Architecture
                 * 20 - deprecated (use method 93 for zstd)
                 * 93 - (Supported, with external DLL) Zstandard (zstd) Compression
                 * 94 - MP3 Compression
                 * 95 - XZ Compression
                 * 96 - JPEG variant
                 * 97 - WavPack compressed data
                 * 98 - (Supported) PPMd version I, Rev 1
                 * 99 - AE-x encryption marker (see APPENDIX E)
                 */

                switch (_compressionMethod)
                {
                case 0:     // The file is stored (no compression)
                case 8:     // The file is Deflated
                case 9:     // Enhanced Deflating using Deflate64(tm)
                case 12:    // The file is BZIP2 algorithm.
                case 14:    // LZMA
                    return(ZipReturn.ZipGood);

                case 20:
                case 93:     // Zstandard (zstd) Compression
                    return(ZipReturn.ZipGood);

                case 98:     // PPMd version I, Rev 1
                    return(ZipReturn.ZipGood);

                default:
                    return(ZipReturn.ZipUnsupportedCompression);
                }
            }
            catch
            {
                return(ZipReturn.ZipCentralDirError);
            }
        }
예제 #3
0
        internal ZipReturn LocalFileHeaderRead(Stream zipFs)
        {
            try
            {
                using (BinaryReader br = new(zipFs, Encoding.UTF8, true))
                {
                    SetStatus(LocalFileStatus.TrrntZip);

                    zipFs.Position = (long)RelativeOffsetOfLocalHeader;
                    uint thisSignature = br.ReadUInt32();
                    if (thisSignature != LocalFileHeaderSignature)
                    {
                        return(ZipReturn.ZipLocalFileHeaderError);
                    }

                    br.ReadUInt16(); // version needed to extract
                    ushort generalPurposeBitFlagLocal = br.ReadUInt16();
                    if (generalPurposeBitFlagLocal != GeneralPurposeBitFlag)
                    {
                        SetStatus(LocalFileStatus.TrrntZip, false);
                    }

                    ushort tshort = br.ReadUInt16();
                    if (tshort != _compressionMethod)
                    {
                        return(ZipReturn.ZipLocalFileHeaderError);
                    }

                    ushort lastModFileTime = br.ReadUInt16();
                    ushort lastModFileDate = br.ReadUInt16();

                    long tTime = CompressUtils.UtcTicksFromDosDateTime(lastModFileDate, lastModFileTime);

                    if (tTime != HeaderLastModified)
                    {
                        SetStatus(LocalFileStatus.DateTimeMisMatch);
                        SetStatus(LocalFileStatus.TrrntZip, false);
                    }

                    LocalFile localHeader = new();
                    localHeader.CRC = ReadCRC(br);
                    ulong localHeaderCompressedSize = br.ReadUInt32();
                    localHeader.UncompressedSize = br.ReadUInt32();
                    ulong localRelativeOffset = 0;

                    ushort fileNameLength   = br.ReadUInt16();
                    ushort extraFieldLength = br.ReadUInt16();


                    byte[] bFileName = br.ReadBytes(fileNameLength);
                    localHeader.Filename = (generalPurposeBitFlagLocal & (1 << 11)) == 0
                        ? CompressUtils.GetString(bFileName)
                        : Encoding.UTF8.GetString(bFileName, 0, fileNameLength);


                    if (extraFieldLength > 0)
                    {
                        byte[] extraField = br.ReadBytes(extraFieldLength);

                        ZipReturn zr = ZipExtraField.ReadExtraField(extraField, bFileName, localHeader, ref localHeaderCompressedSize, ref localRelativeOffset, false);
                        if (zr != ZipReturn.ZipGood)
                        {
                            return(zr);
                        }
                    }

                    if (!CompressUtils.CompareString(Filename, localHeader.Filename))
                    {
                        SetStatus(LocalFileStatus.TrrntZip, false);
                        if (!CompressUtils.CompareStringSlash(Filename.ToLower(), localHeader.Filename.ToLower()))
                        {
                            SetStatus(LocalFileStatus.FilenameMisMatch);
                        }
                    }

                    _dataLocation = (ulong)zipFs.Position;

                    if ((GeneralPurposeBitFlag & 8) == 8)
                    {
                        SetStatus(LocalFileStatus.TrrntZip, false);
                        zipFs.Position += (long)_compressedSize;

                        localHeader.CRC = ReadCRC(br);
                        if (CompressUtils.ByteArrCompare(localHeader.CRC, new byte[] { 0x08, 0x07, 0x4b, 0x50 }))
                        {
                            localHeader.CRC = ReadCRC(br);
                        }

                        if (GetStatus(LocalFileStatus.Zip64))
                        {
                            localHeaderCompressedSize    = br.ReadUInt64();
                            localHeader.UncompressedSize = br.ReadUInt64();
                        }
                        else
                        {
                            localHeaderCompressedSize    = br.ReadUInt32();
                            localHeader.UncompressedSize = br.ReadUInt32();
                        }
                    }

                    if (CompressUtils.IsCodePage437(Filename) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
                    {
                        SetStatus(LocalFileStatus.TrrntZip, false);
                    }


                    if (!CompressUtils.ByteArrCompare(localHeader.CRC, CRC))
                    {
                        return(ZipReturn.ZipLocalFileHeaderError);
                    }

                    if (localHeaderCompressedSize != _compressedSize)
                    {
                        return(ZipReturn.ZipLocalFileHeaderError);
                    }

                    if (localHeader.UncompressedSize != UncompressedSize)
                    {
                        return(ZipReturn.ZipLocalFileHeaderError);
                    }

                    return(ZipReturn.ZipGood);
                }
            }
            catch
            {
                return(ZipReturn.ZipLocalFileHeaderError);
            }
        }