예제 #1
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);
            }
        }