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); } }
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); } }
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); } }