// There is a small chance that something very weird could happen here. The code calling into this function // will ask for a value from the extra field if the field was masked with FF's. It's theoretically possible // that a field was FF's legitimately, and the writer didn't decide to write the corresponding extra field. // Also, at the same time, other fields were masked with FF's to indicate looking in the zip64 record. // Then, the search for the zip64 record will fail because the expected size is wrong, // and a nulled out Zip64ExtraField will be returned. Thus, even though there was Zip64 data, // it will not be used. It is questionable whether this situation is possible to detect // unlike the other functions that have try-pattern semantics, these functions always return a // Zip64ExtraField. If a Zip64 extra field actually doesn't exist, all of the fields in the // returned struct will be null // // If there are more than one Zip64 extra fields, we take the first one that has the expected size // public static Zip64ExtraField GetJustZip64Block(Stream extraFieldStream, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64Field; using (BinaryReader reader = new BinaryReader(extraFieldStream)) { ZipGenericExtraField currentExtraField; while (ZipGenericExtraField.TryReadBlock(reader, extraFieldStream.Length, out currentExtraField)) { if (TryGetZip64BlockFromGenericExtraField(currentExtraField, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64Field)) { return(zip64Field); } } } zip64Field = new Zip64ExtraField(); zip64Field._compressedSize = null; zip64Field._uncompressedSize = null; zip64Field._localHeaderOffset = null; zip64Field._startDiskNumber = null; return(zip64Field); }
public static Zip64ExtraField GetAndRemoveZip64Block(List <ZipGenericExtraField> extraFields, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64ExtraField = new Zip64ExtraField() { _compressedSize = null, _uncompressedSize = null, _localHeaderOffset = null, _startDiskNumber = null }; List <ZipGenericExtraField> zipGenericExtraFields = new List <ZipGenericExtraField>(); bool flag = false; foreach (ZipGenericExtraField extraField in extraFields) { if (extraField.Tag != 1) { continue; } zipGenericExtraFields.Add(extraField); if (flag || !Zip64ExtraField.TryGetZip64BlockFromGenericExtraField(extraField, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64ExtraField)) { continue; } flag = true; } foreach (ZipGenericExtraField zipGenericExtraField in zipGenericExtraFields) { extraFields.Remove(zipGenericExtraField); } return(zip64ExtraField); }
public static Zip64ExtraField GetJustZip64Block(Stream extraFieldStream, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64ExtraField; ZipGenericExtraField zipGenericExtraField; Zip64ExtraField zip64ExtraField1; using (BinaryReader binaryReader = new BinaryReader(extraFieldStream)) { while (ZipGenericExtraField.TryReadBlock(binaryReader, extraFieldStream.Length, out zipGenericExtraField)) { if (!Zip64ExtraField.TryGetZip64BlockFromGenericExtraField(zipGenericExtraField, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64ExtraField)) { continue; } zip64ExtraField1 = zip64ExtraField; return(zip64ExtraField1); } zip64ExtraField = new Zip64ExtraField() { _compressedSize = null, _uncompressedSize = null, _localHeaderOffset = null, _startDiskNumber = null }; return(zip64ExtraField); } return(zip64ExtraField1); }
public static List <ZipGenericExtraField> GetExtraFields(BinaryReader reader) { List <ZipGenericExtraField> zipGenericExtraFields; reader.BaseStream.Seek((long)26, SeekOrigin.Current); ushort num = reader.ReadUInt16(); ushort num1 = reader.ReadUInt16(); reader.BaseStream.Seek((long)num, SeekOrigin.Current); using (Stream subReadStream = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, (long)num1)) { zipGenericExtraFields = ZipGenericExtraField.ParseExtraField(subReadStream); } Zip64ExtraField.RemoveZip64Blocks(zipGenericExtraFields); return(zipGenericExtraFields); }
public static Zip64ExtraField GetAndRemoveZip64Block(List <ZipGenericExtraField> extraFields, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64Field = new Zip64ExtraField(); zip64Field._compressedSize = null; zip64Field._uncompressedSize = null; zip64Field._localHeaderOffset = null; zip64Field._startDiskNumber = null; List <ZipGenericExtraField> markedForDelete = new List <ZipGenericExtraField>(); bool zip64FieldFound = false; foreach (ZipGenericExtraField ef in extraFields) { if (ef.Tag == TagConstant) { markedForDelete.Add(ef); if (!zip64FieldFound) { if (TryGetZip64BlockFromGenericExtraField(ef, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64Field)) { zip64FieldFound = true; } } } } foreach (ZipGenericExtraField ef in markedForDelete) { extraFields.Remove(ef); } return(zip64Field); }
public static List <ZipGenericExtraField> GetExtraFields(BinaryReader reader) { // assumes that TrySkipBlock has already been called, so we don't have to validate twice List <ZipGenericExtraField> result; const int OffsetToFilenameLength = 26; // from the point before the signature reader.BaseStream.Seek(OffsetToFilenameLength, SeekOrigin.Current); ushort filenameLength = reader.ReadUInt16(); ushort extraFieldLength = reader.ReadUInt16(); reader.BaseStream.Seek(filenameLength, SeekOrigin.Current); using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, extraFieldLength)) { result = ZipGenericExtraField.ParseExtraField(str); } Zip64ExtraField.RemoveZip64Blocks(result); return(result); }
// return value is true if we allocated an extra field for 64 bit headers, un/compressed size private bool WriteLocalFileHeader(bool isEmptyFile) { BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream); // _entryname only gets set when we read in or call moveTo. MoveTo does a check, and // reading in should not be able to produce an entryname longer than ushort.MaxValue Debug.Assert(_storedEntryNameBytes.Length <= ushort.MaxValue); // decide if we need the Zip64 extra field: Zip64ExtraField zip64ExtraField = new Zip64ExtraField(); bool zip64Used = false; uint compressedSizeTruncated, uncompressedSizeTruncated; // if we already know that we have an empty file don't worry about anything, just do a straight shot of the header if (isEmptyFile) { CompressionMethod = CompressionMethodValues.Stored; compressedSizeTruncated = 0; uncompressedSizeTruncated = 0; Debug.Assert(_compressedSize == 0); Debug.Assert(_uncompressedSize == 0); Debug.Assert(_crc32 == 0); } else { // if we have a non-seekable stream, don't worry about sizes at all, and just set the right bit // if we are using the data descriptor, then sizes and crc should be set to 0 in the header if (_archive.Mode == ZipArchiveMode.Create && _archive.ArchiveStream.CanSeek == false && !isEmptyFile) { _generalPurposeBitFlag |= BitFlagValues.DataDescriptor; zip64Used = false; compressedSizeTruncated = 0; uncompressedSizeTruncated = 0; // the crc should not have been set if we are in create mode, but clear it just to be sure Debug.Assert(_crc32 == 0); } else // if we are not in streaming mode, we have to decide if we want to write zip64 headers { if (SizesTooLarge() #if DEBUG_FORCE_ZIP64 || (_archive._forceZip64 && _archive.Mode == ZipArchiveMode.Update) #endif ) { zip64Used = true; compressedSizeTruncated = ZipHelper.Mask32Bit; uncompressedSizeTruncated = ZipHelper.Mask32Bit; // prepare Zip64 extra field object. If we have one of the sizes, the other must go in there zip64ExtraField.CompressedSize = _compressedSize; zip64ExtraField.UncompressedSize = _uncompressedSize; VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); } else { zip64Used = false; compressedSizeTruncated = (uint)_compressedSize; uncompressedSizeTruncated = (uint)_uncompressedSize; } } } // save offset _offsetOfLocalHeader = writer.BaseStream.Position; // calculate extra field. if zip64 stuff + original extraField aren't going to fit, dump the original extraField, because this is more important int bigExtraFieldLength = (zip64Used ? zip64ExtraField.TotalSize : 0) + (_lhUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_lhUnknownExtraFields) : 0); ushort extraFieldLength; if (bigExtraFieldLength > ushort.MaxValue) { extraFieldLength = (ushort)(zip64Used ? zip64ExtraField.TotalSize : 0); _lhUnknownExtraFields = null; } else { extraFieldLength = (ushort)bigExtraFieldLength; } // write header writer.Write(ZipLocalFileHeader.SignatureConstant); writer.Write((ushort)_versionToExtract); writer.Write((ushort)_generalPurposeBitFlag); writer.Write((ushort)CompressionMethod); writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime)); // uint writer.Write(_crc32); // uint writer.Write(compressedSizeTruncated); // uint writer.Write(uncompressedSizeTruncated); // uint writer.Write((ushort)_storedEntryNameBytes.Length); writer.Write(extraFieldLength); // ushort writer.Write(_storedEntryNameBytes); if (zip64Used) { zip64ExtraField.WriteBlock(_archive.ArchiveStream); } if (_lhUnknownExtraFields != null) { ZipGenericExtraField.WriteAllBlocks(_lhUnknownExtraFields, _archive.ArchiveStream); } return(zip64Used); }
private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber, out Zip64ExtraField zip64Block) { zip64Block = new Zip64ExtraField(); zip64Block._compressedSize = null; zip64Block._uncompressedSize = null; zip64Block._localHeaderOffset = null; zip64Block._startDiskNumber = null; if (extraField.Tag != TagConstant) { return(false); } // this pattern needed because nested using blocks trigger CA2202 MemoryStream?ms = null; try { ms = new MemoryStream(extraField.Data); using (BinaryReader reader = new BinaryReader(ms)) { ms = null; zip64Block._size = extraField.Size; ushort expectedSize = 0; if (readUncompressedSize) { expectedSize += 8; } if (readCompressedSize) { expectedSize += 8; } if (readLocalHeaderOffset) { expectedSize += 8; } if (readStartDiskNumber) { expectedSize += 4; } // if it is not the expected size, perhaps there is another extra field that matches if (expectedSize != zip64Block._size) { return(false); } if (readUncompressedSize) { zip64Block._uncompressedSize = reader.ReadInt64(); } if (readCompressedSize) { zip64Block._compressedSize = reader.ReadInt64(); } if (readLocalHeaderOffset) { zip64Block._localHeaderOffset = reader.ReadInt64(); } if (readStartDiskNumber) { zip64Block._startDiskNumber = reader.ReadInt32(); } // original values are unsigned, so implies value is too big to fit in signed integer if (zip64Block._uncompressedSize < 0) { throw new InvalidDataException(SR.FieldTooBigUncompressedSize); } if (zip64Block._compressedSize < 0) { throw new InvalidDataException(SR.FieldTooBigCompressedSize); } if (zip64Block._localHeaderOffset < 0) { throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset); } if (zip64Block._startDiskNumber < 0) { throw new InvalidDataException(SR.FieldTooBigStartDiskNumber); } return(true); } } finally { if (ms != null) { ms.Dispose(); } } }
//if saveExtraFieldsAndComments is false, FileComment and ExtraFields will be null //in either case, the zip64 extra field info will be incorporated into other fields static public Boolean TryReadBlock(BinaryReader reader, Boolean saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header) { header = new ZipCentralDirectoryFileHeader(); if (reader.ReadUInt32() != SignatureConstant) { return(false); } header.VersionMadeBy = reader.ReadUInt16(); header.VersionNeededToExtract = reader.ReadUInt16(); header.GeneralPurposeBitFlag = reader.ReadUInt16(); header.CompressionMethod = reader.ReadUInt16(); header.LastModified = reader.ReadUInt32(); header.Crc32 = reader.ReadUInt32(); UInt32 compressedSizeSmall = reader.ReadUInt32(); UInt32 uncompressedSizeSmall = reader.ReadUInt32(); header.FilenameLength = reader.ReadUInt16(); header.ExtraFieldLength = reader.ReadUInt16(); header.FileCommentLength = reader.ReadUInt16(); UInt16 diskNumberStartSmall = reader.ReadUInt16(); header.InternalFileAttributes = reader.ReadUInt16(); header.ExternalFileAttributes = reader.ReadUInt32(); UInt32 relativeOffsetOfLocalHeaderSmall = reader.ReadUInt32(); header.Filename = reader.ReadBytes(header.FilenameLength); Boolean uncompressedSizeInZip64 = uncompressedSizeSmall == ZipHelper.Mask32Bit; Boolean compressedSizeInZip64 = compressedSizeSmall == ZipHelper.Mask32Bit; Boolean relativeOffsetInZip64 = relativeOffsetOfLocalHeaderSmall == ZipHelper.Mask32Bit; Boolean diskNumberStartInZip64 = diskNumberStartSmall == ZipHelper.Mask16Bit; Zip64ExtraField zip64; using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, header.ExtraFieldLength)) { if (saveExtraFieldsAndComments) { header.ExtraFields = ZipGenericExtraField.ParseExtraField(str); zip64 = Zip64ExtraField.GetAndRemoveZip64Block(header.ExtraFields, uncompressedSizeInZip64, compressedSizeInZip64, relativeOffsetInZip64, diskNumberStartInZip64); } else { header.ExtraFields = null; zip64 = Zip64ExtraField.GetJustZip64Block(str, uncompressedSizeInZip64, compressedSizeInZip64, relativeOffsetInZip64, diskNumberStartInZip64); } } if (saveExtraFieldsAndComments) { header.FileComment = reader.ReadBytes(header.FileCommentLength); } else { reader.BaseStream.Position += header.FileCommentLength; header.FileComment = null; } header.UncompressedSize = zip64.UncompressedSize == null ? uncompressedSizeSmall : zip64.UncompressedSize.Value; header.CompressedSize = zip64.CompressedSize == null ? compressedSizeSmall : zip64.CompressedSize.Value; header.RelativeOffsetOfLocalHeader = zip64.LocalHeaderOffset == null ? relativeOffsetOfLocalHeaderSmall : zip64.LocalHeaderOffset.Value; header.DiskNumberStart = zip64.StartDiskNumber == null ? diskNumberStartSmall : zip64.StartDiskNumber.Value; return(true); }
private bool WriteLocalFileHeader(bool isEmptyFile) { uint num; uint num1; ushort num2; ushort totalSize; ushort num3; object obj; BinaryWriter binaryWriter = new BinaryWriter(this._archive.ArchiveStream); Zip64ExtraField nullable = new Zip64ExtraField(); bool flag = false; if (isEmptyFile) { this.CompressionMethod = ZipArchiveEntry.CompressionMethodValues.Stored; num = 0; num1 = 0; } else if (this._archive.Mode == ZipArchiveMode.Create && !this._archive.ArchiveStream.CanSeek && !isEmptyFile) { this._generalPurposeBitFlag |= ZipArchiveEntry.BitFlagValues.DataDescriptor; flag = false; num = 0; num1 = 0; } else if (!this.SizesTooLarge()) { flag = false; num = (uint)this._compressedSize; num1 = (uint)this._uncompressedSize; } else { flag = true; num = -1; num1 = -1; nullable.CompressedSize = new long?(this._compressedSize); nullable.UncompressedSize = new long?(this._uncompressedSize); this.VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); } this._offsetOfLocalHeader = binaryWriter.BaseStream.Position; if (flag) { totalSize = nullable.TotalSize; } else { totalSize = 0; } if (this._lhUnknownExtraFields != null) { num3 = (ushort)ZipGenericExtraField.TotalSize(this._lhUnknownExtraFields); } else { num3 = 0; } int num4 = totalSize + num3; if (num4 <= 65535) { num2 = (ushort)num4; } else { if (flag) { obj = nullable.TotalSize; } else { obj = null; } num2 = (ushort)obj; this._lhUnknownExtraFields = null; } binaryWriter.Write((uint)67324752); binaryWriter.Write((ushort)this._versionToExtract); binaryWriter.Write((ushort)this._generalPurposeBitFlag); binaryWriter.Write((ushort)this.CompressionMethod); binaryWriter.Write(ZipHelper.DateTimeToDosTime(this._lastModified.DateTime)); binaryWriter.Write(this._crc32); binaryWriter.Write(num); binaryWriter.Write(num1); binaryWriter.Write((ushort)((int)this._storedEntryNameBytes.Length)); binaryWriter.Write(num2); binaryWriter.Write(this._storedEntryNameBytes); if (flag) { nullable.WriteBlock(this._archive.ArchiveStream); } if (this._lhUnknownExtraFields != null) { ZipGenericExtraField.WriteAllBlocks(this._lhUnknownExtraFields, this._archive.ArchiveStream); } return(flag); }
/* There is a small chance that something very weird could happen here. The code calling into this function * will ask for a value from the extra field if the field was masked with FF's. It's theoretically possible * that a field was FF's legitimately, and the writer didn't decide to write the corresponding extra field. * Also, at the same time, other fields were masked with FF's to indicate looking in the zip64 record. * Then, the search for the zip64 record will fail because the expected size is wrong, * and a nulled out Zip64ExtraField will be returned. Thus, even though there was Zip64 data, * it will not be used. It is questionable whether this situation is possible to detect */ /* unlike the other functions that have try-pattern semantics, these functions always return a * Zip64ExtraField. If a Zip64 extra field actually doesn't exist, all of the fields in the * returned struct will be null * * If there are more than one Zip64 extra fields, we take the first one that has the expected size */ public static Zip64ExtraField GetJustZip64Block(Stream extraFieldStream, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64Field; using (BinaryReader reader = new BinaryReader(extraFieldStream)) { ZipGenericExtraField currentExtraField; while (ZipGenericExtraField.TryReadBlock(reader, extraFieldStream.Length, out currentExtraField)) { if (TryGetZip64BlockFromGenericExtraField(currentExtraField, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64Field)) { return zip64Field; } } } zip64Field = new Zip64ExtraField(); zip64Field._compressedSize = null; zip64Field._uncompressedSize = null; zip64Field._localHeaderOffset = null; zip64Field._startDiskNumber = null; return zip64Field; }
//return value is true if we allocated an extra field for 64 bit headers, un/compressed size private Boolean WriteLocalFileHeader(Boolean isEmptyFile) { BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream); //_entryname only gets set when we read in or call moveTo. MoveTo does a check, and //reading in should not be able to produce a entryname longer than UInt16.MaxValue Debug.Assert(_storedEntryNameBytes.Length <= UInt16.MaxValue); //decide if we need the Zip64 extra field: Zip64ExtraField zip64ExtraField = new Zip64ExtraField(); Boolean zip64Used = false; UInt32 compressedSizeTruncated, uncompressedSizeTruncated; //if we already know that we have an empty file don't worry about anything, just do a straight shot of the header if (isEmptyFile) { CompressionMethod = CompressionMethodValues.Stored; compressedSizeTruncated = 0; uncompressedSizeTruncated = 0; Debug.Assert(_compressedSize == 0); Debug.Assert(_uncompressedSize == 0); Debug.Assert(_crc32 == 0); } else { //if we have a non-seekable stream, don't worry about sizes at all, and just set the right bit //if we are using the data descriptor, then sizes and crc should be set to 0 in the header if (_archive.Mode == ZipArchiveMode.Create && _archive.ArchiveStream.CanSeek == false && !isEmptyFile) { _generalPurposeBitFlag |= BitFlagValues.DataDescriptor; zip64Used = false; compressedSizeTruncated = 0; uncompressedSizeTruncated = 0; //the crc should not have been set if we are in create mode, but clear it just to be sure Debug.Assert(_crc32 == 0); } else //if we are not in streaming mode, we have to decide if we want to write zip64 headers { if (SizesTooLarge() #if DEBUG_FORCE_ZIP64 || (_archive._forceZip64 && _archive.Mode == ZipArchiveMode.Update) #endif ) { zip64Used = true; compressedSizeTruncated = ZipHelper.Mask32Bit; uncompressedSizeTruncated = ZipHelper.Mask32Bit; //prepare Zip64 extra field object. If we have one of the sizes, the other must go in there zip64ExtraField.CompressedSize = _compressedSize; zip64ExtraField.UncompressedSize = _uncompressedSize; VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); } else { zip64Used = false; compressedSizeTruncated = (UInt32)_compressedSize; uncompressedSizeTruncated = (UInt32)_uncompressedSize; } } } //save offset _offsetOfLocalHeader = writer.BaseStream.Position; //calculate extra field. if zip64 stuff + original extraField aren't going to fit, dump the original extraField, because this is more important Int32 bigExtraFieldLength = (zip64Used ? zip64ExtraField.TotalSize : 0) + (_lhUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_lhUnknownExtraFields) : 0); UInt16 extraFieldLength; if (bigExtraFieldLength > UInt16.MaxValue) { extraFieldLength = (UInt16)(zip64Used ? zip64ExtraField.TotalSize : 0); _lhUnknownExtraFields = null; } else { extraFieldLength = (UInt16)bigExtraFieldLength; } //write header writer.Write(ZipLocalFileHeader.SignatureConstant); writer.Write((UInt16)_versionToExtract); writer.Write((UInt16)_generalPurposeBitFlag); writer.Write((UInt16)CompressionMethod); writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime)); //UInt32 writer.Write(_crc32); //UInt32 writer.Write(compressedSizeTruncated); //UInt32 writer.Write(uncompressedSizeTruncated); //UInt32 writer.Write((UInt16)_storedEntryNameBytes.Length); writer.Write(extraFieldLength); //UInt16 writer.Write(_storedEntryNameBytes); if (zip64Used) zip64ExtraField.WriteBlock(_archive.ArchiveStream); if (_lhUnknownExtraFields != null) ZipGenericExtraField.WriteAllBlocks(_lhUnknownExtraFields, _archive.ArchiveStream); return zip64Used; }
internal void WriteCentralDirectoryFileHeader() { uint num; uint num1; uint num2; ushort num3; ushort totalSize; ushort num4; ushort length; object obj; BinaryWriter binaryWriter = new BinaryWriter(this._archive.ArchiveStream); Zip64ExtraField nullable = new Zip64ExtraField(); bool flag = false; if (!this.SizesTooLarge()) { num = (uint)this._compressedSize; num1 = (uint)this._uncompressedSize; } else { flag = true; num = -1; num1 = -1; nullable.CompressedSize = new long?(this._compressedSize); nullable.UncompressedSize = new long?(this._uncompressedSize); } if (this._offsetOfLocalHeader <= (ulong)-1) { num2 = (uint)this._offsetOfLocalHeader; } else { flag = true; num2 = -1; nullable.LocalHeaderOffset = new long?(this._offsetOfLocalHeader); } if (flag) { this.VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); } if (flag) { totalSize = nullable.TotalSize; } else { totalSize = 0; } if (this._cdUnknownExtraFields != null) { num4 = (ushort)ZipGenericExtraField.TotalSize(this._cdUnknownExtraFields); } else { num4 = 0; } int num5 = totalSize + num4; if (num5 <= 65535) { num3 = (ushort)num5; } else { if (flag) { obj = nullable.TotalSize; } else { obj = null; } num3 = (ushort)obj; this._cdUnknownExtraFields = null; } binaryWriter.Write((uint)33639248); binaryWriter.Write((ushort)this._versionToExtract); binaryWriter.Write((ushort)this._versionToExtract); binaryWriter.Write((ushort)this._generalPurposeBitFlag); binaryWriter.Write((ushort)this.CompressionMethod); binaryWriter.Write(ZipHelper.DateTimeToDosTime(this._lastModified.DateTime)); binaryWriter.Write(this._crc32); binaryWriter.Write(num); binaryWriter.Write(num1); binaryWriter.Write((ushort)((int)this._storedEntryNameBytes.Length)); binaryWriter.Write(num3); BinaryWriter binaryWriter1 = binaryWriter; if (this._fileComment != null) { length = (ushort)((int)this._fileComment.Length); } else { length = 0; } binaryWriter1.Write(length); binaryWriter.Write((ushort)0); binaryWriter.Write((ushort)0); binaryWriter.Write(this._externalFileAttr); binaryWriter.Write(num2); binaryWriter.Write(this._storedEntryNameBytes); if (flag) { nullable.WriteBlock(this._archive.ArchiveStream); } if (this._cdUnknownExtraFields != null) { ZipGenericExtraField.WriteAllBlocks(this._cdUnknownExtraFields, this._archive.ArchiveStream); } if (this._fileComment != null) { binaryWriter.Write(this._fileComment); } }
private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber, out Zip64ExtraField zip64Block) { bool flag; zip64Block = new Zip64ExtraField() { _compressedSize = null, _uncompressedSize = null, _localHeaderOffset = null, _startDiskNumber = null }; if (extraField.Tag != 1) { return(false); } MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(extraField.Data); using (BinaryReader binaryReader = new BinaryReader(memoryStream)) { memoryStream = null; zip64Block._size = extraField.Size; ushort num = 0; if (readUncompressedSize) { num = (ushort)(num + 8); } if (readCompressedSize) { num = (ushort)(num + 8); } if (readLocalHeaderOffset) { num = (ushort)(num + 8); } if (readStartDiskNumber) { num = (ushort)(num + 4); } if (num == zip64Block._size) { if (readUncompressedSize) { zip64Block._uncompressedSize = new long?(binaryReader.ReadInt64()); } if (readCompressedSize) { zip64Block._compressedSize = new long?(binaryReader.ReadInt64()); } if (readLocalHeaderOffset) { zip64Block._localHeaderOffset = new long?(binaryReader.ReadInt64()); } if (readStartDiskNumber) { zip64Block._startDiskNumber = new int?(binaryReader.ReadInt32()); } long?nullable = zip64Block._uncompressedSize; long num1 = (long)0; if ((nullable.GetValueOrDefault() < num1 ? nullable.HasValue : false)) { throw new InvalidDataException(Messages.FieldTooBigUncompressedSize); } nullable = zip64Block._compressedSize; num1 = (long)0; if ((nullable.GetValueOrDefault() < num1 ? nullable.HasValue : false)) { throw new InvalidDataException(Messages.FieldTooBigCompressedSize); } nullable = zip64Block._localHeaderOffset; num1 = (long)0; if ((nullable.GetValueOrDefault() < num1 ? nullable.HasValue : false)) { throw new InvalidDataException(Messages.FieldTooBigLocalHeaderOffset); } int?nullable1 = zip64Block._startDiskNumber; if ((nullable1.GetValueOrDefault() < 0 ? nullable1.HasValue : false)) { throw new InvalidDataException(Messages.FieldTooBigStartDiskNumber); } flag = true; } else { flag = false; } } } finally { if (memoryStream != null) { memoryStream.Close(); } } return(flag); }
//should only throw an exception in extremely exceptional cases because it is called from dispose internal void WriteCentralDirectoryFileHeader() { //This part is simple, because we should definitely know the sizes by this time BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream); //_entryname only gets set when we read in or call moveTo. MoveTo does a check, and //reading in should not be able to produce a entryname longer than UInt16.MaxValue Debug.Assert(_storedEntryNameBytes.Length <= UInt16.MaxValue); //decide if we need the Zip64 extra field: Zip64ExtraField zip64ExtraField = new Zip64ExtraField(); UInt32 compressedSizeTruncated, uncompressedSizeTruncated, offsetOfLocalHeaderTruncated; Boolean zip64Needed = false; if (SizesTooLarge() #if DEBUG_FORCE_ZIP64 || _archive._forceZip64 #endif ) { zip64Needed = true; compressedSizeTruncated = ZipHelper.Mask32Bit; uncompressedSizeTruncated = ZipHelper.Mask32Bit; //If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways zip64ExtraField.CompressedSize = _compressedSize; zip64ExtraField.UncompressedSize = _uncompressedSize; } else { compressedSizeTruncated = (UInt32)_compressedSize; uncompressedSizeTruncated = (UInt32)_uncompressedSize; } if (_offsetOfLocalHeader > UInt32.MaxValue #if DEBUG_FORCE_ZIP64 || _archive._forceZip64 #endif ) { zip64Needed = true; offsetOfLocalHeaderTruncated = ZipHelper.Mask32Bit; //If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways zip64ExtraField.LocalHeaderOffset = _offsetOfLocalHeader; } else { offsetOfLocalHeaderTruncated = (UInt32)_offsetOfLocalHeader; } if (zip64Needed) VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); //determine if we can fit zip64 extra field and original extra fields all in Int32 bigExtraFieldLength = (zip64Needed ? zip64ExtraField.TotalSize : 0) + (_cdUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_cdUnknownExtraFields) : 0); UInt16 extraFieldLength; if (bigExtraFieldLength > UInt16.MaxValue) { extraFieldLength = (UInt16)(zip64Needed ? zip64ExtraField.TotalSize : 0); _cdUnknownExtraFields = null; } else { extraFieldLength = (UInt16)bigExtraFieldLength; } writer.Write(ZipCentralDirectoryFileHeader.SignatureConstant); // Central directory file header signature (4 bytes) writer.Write((byte)_versionMadeBySpecification); // Version made by Specification (version) (1 byte) writer.Write((byte)CurrentZipPlatform); // Version made by Compatibility (type) (1 byte) writer.Write((UInt16)_versionToExtract); // Minimum version needed to extract (2 bytes) writer.Write((UInt16)_generalPurposeBitFlag); // General Purpose bit flag (2 bytes) writer.Write((UInt16)CompressionMethod); // The Compression method (2 bytes) writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime)); // File last modification time and date (4 bytes) writer.Write(_crc32); // CRC-32 (4 bytes) writer.Write(compressedSizeTruncated); // Compressed Size (4 bytes) writer.Write(uncompressedSizeTruncated); // Uncompressed Size (4 bytes) writer.Write((UInt16)_storedEntryNameBytes.Length); // File Name Length (2 bytes) writer.Write(extraFieldLength); // Extra Field Length (2 bytes) // This should hold because of how we read it originally in ZipCentralDirectoryFileHeader: Debug.Assert((_fileComment == null) || (_fileComment.Length <= UInt16.MaxValue)); writer.Write(_fileComment != null ? (UInt16)_fileComment.Length : (UInt16)0); //file comment length writer.Write((UInt16)0); //disk number start writer.Write((UInt16)0); //internal file attributes writer.Write((UInt32)0); //external file attributes writer.Write(offsetOfLocalHeaderTruncated); //offset of local header writer.Write(_storedEntryNameBytes); //write extra fields if (zip64Needed) zip64ExtraField.WriteBlock(_archive.ArchiveStream); if (_cdUnknownExtraFields != null) ZipGenericExtraField.WriteAllBlocks(_cdUnknownExtraFields, _archive.ArchiveStream); if (_fileComment != null) writer.Write(_fileComment); }
public static bool TryValidateBlock(BinaryReader reader, ZipArchiveEntry entry) { const int OffsetToFilename = 26; // from the point after the signature if (reader.ReadUInt32() != SignatureConstant) { return(false); } if (reader.BaseStream.Length < reader.BaseStream.Position + OffsetToFilename) { return(false); } reader.BaseStream.Seek(2, SeekOrigin.Current); // skipping minimum version (using min version from central directory header) uint dataDescriptorBit = reader.ReadUInt16() & (uint)ZipArchiveEntry.BitFlagValues.DataDescriptor; reader.BaseStream.Seek(10, SeekOrigin.Current); // skipping bytes used for Compression method (2 bytes), last modification time and date (4 bytes) and CRC (4 bytes) long compressedSize = reader.ReadUInt32(); long uncompressedSize = reader.ReadUInt32(); int filenameLength = reader.ReadUInt16(); uint extraFieldLength = reader.ReadUInt16(); if (reader.BaseStream.Length < reader.BaseStream.Position + filenameLength + extraFieldLength) { return(false); } reader.BaseStream.Seek(filenameLength, SeekOrigin.Current); // skipping Filename long endExtraFields = reader.BaseStream.Position + extraFieldLength; if (dataDescriptorBit == 0) { bool isUncompressedSizeInZip64 = uncompressedSize == ZipHelper.Mask32Bit; bool isCompressedSizeInZip64 = compressedSize == ZipHelper.Mask32Bit; Zip64ExtraField zip64; // Ideally we should also check if the minimumVersion is 64 bit or above, but there could zip files for which this version is not set correctly if (isUncompressedSizeInZip64 || isCompressedSizeInZip64) { zip64 = Zip64ExtraField.GetJustZip64Block(new SubReadStream(reader.BaseStream, reader.BaseStream.Position, extraFieldLength), isUncompressedSizeInZip64, isCompressedSizeInZip64, false, false); if (zip64.UncompressedSize != null) { uncompressedSize = zip64.UncompressedSize.Value; } if (zip64.CompressedSize != null) { compressedSize = zip64.CompressedSize.Value; } } reader.BaseStream.AdvanceToPosition(endExtraFields); } else { if (reader.BaseStream.Length < reader.BaseStream.Position + extraFieldLength + entry.CompressedLength + 4) { return(false); } reader.BaseStream.Seek(extraFieldLength + entry.CompressedLength, SeekOrigin.Current); // seek to end of compressed file from which Data descriptor starts uint dataDescriptorSignature = reader.ReadUInt32(); bool wasDataDescriptorSignatureRead = false; int seekSize = 0; if (dataDescriptorSignature == DataDescriptorSignature) { wasDataDescriptorSignatureRead = true; seekSize = 4; } bool is64bit = entry._versionToExtract >= ZipVersionNeededValues.Zip64; seekSize += (is64bit ? 8 : 4) * 2; // if Zip64 read by 8 bytes else 4 bytes 2 times (compressed and uncompressed size) if (reader.BaseStream.Length < reader.BaseStream.Position + seekSize) { return(false); } // dataDescriptorSignature is optional, if it was the DataDescriptorSignature we need to skip CRC 4 bytes else we can assume CRC is alreadyskipped if (wasDataDescriptorSignatureRead) { reader.BaseStream.Seek(4, SeekOrigin.Current); } if (is64bit) { compressedSize = reader.ReadInt64(); uncompressedSize = reader.ReadInt64(); } else { compressedSize = reader.ReadInt32(); uncompressedSize = reader.ReadInt32(); } reader.BaseStream.Seek(-seekSize - entry.CompressedLength - 4, SeekOrigin.Current); // Seek back to the beginning of compressed stream } if (entry.CompressedLength != compressedSize) { return(false); } if (entry.Length != uncompressedSize) { return(false); } return(true); }
// should only throw an exception in extremely exceptional cases because it is called from dispose internal void WriteCentralDirectoryFileHeader() { // This part is simple, because we should definitely know the sizes by this time BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream); // _entryname only gets set when we read in or call moveTo. MoveTo does a check, and // reading in should not be able to produce an entryname longer than ushort.MaxValue Debug.Assert(_storedEntryNameBytes.Length <= ushort.MaxValue); // decide if we need the Zip64 extra field: Zip64ExtraField zip64ExtraField = new Zip64ExtraField(); uint compressedSizeTruncated, uncompressedSizeTruncated, offsetOfLocalHeaderTruncated; bool zip64Needed = false; if (SizesTooLarge() #if DEBUG_FORCE_ZIP64 || _archive._forceZip64 #endif ) { zip64Needed = true; compressedSizeTruncated = ZipHelper.Mask32Bit; uncompressedSizeTruncated = ZipHelper.Mask32Bit; // If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways zip64ExtraField.CompressedSize = _compressedSize; zip64ExtraField.UncompressedSize = _uncompressedSize; } else { compressedSizeTruncated = (uint)_compressedSize; uncompressedSizeTruncated = (uint)_uncompressedSize; } if (_offsetOfLocalHeader > uint.MaxValue #if DEBUG_FORCE_ZIP64 || _archive._forceZip64 #endif ) { zip64Needed = true; offsetOfLocalHeaderTruncated = ZipHelper.Mask32Bit; // If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways zip64ExtraField.LocalHeaderOffset = _offsetOfLocalHeader; } else { offsetOfLocalHeaderTruncated = (uint)_offsetOfLocalHeader; } if (zip64Needed) { VersionToExtractAtLeast(ZipVersionNeededValues.Zip64); } // determine if we can fit zip64 extra field and original extra fields all in int bigExtraFieldLength = (zip64Needed ? zip64ExtraField.TotalSize : 0) + (_cdUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_cdUnknownExtraFields) : 0); ushort extraFieldLength; if (bigExtraFieldLength > ushort.MaxValue) { extraFieldLength = (ushort)(zip64Needed ? zip64ExtraField.TotalSize : 0); _cdUnknownExtraFields = null; } else { extraFieldLength = (ushort)bigExtraFieldLength; } writer.Write(ZipCentralDirectoryFileHeader.SignatureConstant); // Central directory file header signature (4 bytes) writer.Write((byte)_versionMadeBySpecification); // Version made by Specification (version) (1 byte) writer.Write((byte)CurrentZipPlatform); // Version made by Compatibility (type) (1 byte) writer.Write((ushort)_versionToExtract); // Minimum version needed to extract (2 bytes) writer.Write((ushort)_generalPurposeBitFlag); // General Purpose bit flag (2 bytes) writer.Write((ushort)CompressionMethod); // The Compression method (2 bytes) writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime)); // File last modification time and date (4 bytes) writer.Write(_crc32); // CRC-32 (4 bytes) writer.Write(compressedSizeTruncated); // Compressed Size (4 bytes) writer.Write(uncompressedSizeTruncated); // Uncompressed Size (4 bytes) writer.Write((ushort)_storedEntryNameBytes.Length); // File Name Length (2 bytes) writer.Write(extraFieldLength); // Extra Field Length (2 bytes) // This should hold because of how we read it originally in ZipCentralDirectoryFileHeader: Debug.Assert((_fileComment == null) || (_fileComment.Length <= ushort.MaxValue)); writer.Write(_fileComment != null ? (ushort)_fileComment.Length : (ushort)0); // file comment length writer.Write((ushort)0); // disk number start writer.Write((ushort)0); // internal file attributes writer.Write(_externalFileAttr); // external file attributes writer.Write(offsetOfLocalHeaderTruncated); // offset of local header writer.Write(_storedEntryNameBytes); // write extra fields if (zip64Needed) { zip64ExtraField.WriteBlock(_archive.ArchiveStream); } if (_cdUnknownExtraFields != null) { ZipGenericExtraField.WriteAllBlocks(_cdUnknownExtraFields, _archive.ArchiveStream); } if (_fileComment != null) { writer.Write(_fileComment); } }
private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber, out Zip64ExtraField zip64Block) { zip64Block = default; zip64Block._compressedSize = null; zip64Block._uncompressedSize = null; zip64Block._localHeaderOffset = null; zip64Block._startDiskNumber = null; if (extraField.Tag != TagConstant) { return(false); } zip64Block._size = extraField.Size; using (MemoryStream ms = new MemoryStream(extraField.Data)) using (BinaryReader reader = new BinaryReader(ms)) { // The spec section 4.5.3: // The order of the fields in the zip64 extended // information record is fixed, but the fields MUST // only appear if the corresponding Local or Central // directory record field is set to 0xFFFF or 0xFFFFFFFF. // However tools commonly write the fields anyway; the prevailing convention // is to respect the size, but only actually use the values if their 32 bit // values were all 0xFF. if (extraField.Size < sizeof(long)) { return(true); } long value64 = reader.ReadInt64(); if (readUncompressedSize) { zip64Block._uncompressedSize = value64; } if (ms.Position > extraField.Size - sizeof(long)) { return(true); } value64 = reader.ReadInt64(); if (readCompressedSize) { zip64Block._compressedSize = value64; } if (ms.Position > extraField.Size - sizeof(long)) { return(true); } value64 = reader.ReadInt64(); if (readLocalHeaderOffset) { zip64Block._localHeaderOffset = value64; } if (ms.Position > extraField.Size - sizeof(int)) { return(true); } int value32 = reader.ReadInt32(); if (readStartDiskNumber) { zip64Block._startDiskNumber = value32; } // original values are unsigned, so implies value is too big to fit in signed integer if (zip64Block._uncompressedSize < 0) { throw new InvalidDataException(SR.FieldTooBigUncompressedSize); } if (zip64Block._compressedSize < 0) { throw new InvalidDataException(SR.FieldTooBigCompressedSize); } if (zip64Block._localHeaderOffset < 0) { throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset); } if (zip64Block._startDiskNumber < 0) { throw new InvalidDataException(SR.FieldTooBigStartDiskNumber); } return(true); } }
private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber, out Zip64ExtraField zip64Block) { zip64Block = new Zip64ExtraField(); zip64Block._compressedSize = null; zip64Block._uncompressedSize = null; zip64Block._localHeaderOffset = null; zip64Block._startDiskNumber = null; if (extraField.Tag != TagConstant) return false; //this pattern needed because nested using blocks trigger CA2202 MemoryStream ms = null; try { ms = new MemoryStream(extraField.Data); using (BinaryReader reader = new BinaryReader(ms)) { ms = null; zip64Block._size = extraField.Size; ushort expectedSize = 0; if (readUncompressedSize) expectedSize += 8; if (readCompressedSize) expectedSize += 8; if (readLocalHeaderOffset) expectedSize += 8; if (readStartDiskNumber) expectedSize += 4; //if it is not the expected size, perhaps there is another extra field that matches if (expectedSize != zip64Block._size) return false; if (readUncompressedSize) zip64Block._uncompressedSize = reader.ReadInt64(); if (readCompressedSize) zip64Block._compressedSize = reader.ReadInt64(); if (readLocalHeaderOffset) zip64Block._localHeaderOffset = reader.ReadInt64(); if (readStartDiskNumber) zip64Block._startDiskNumber = reader.ReadInt32(); //original values are unsigned, so implies value is too big to fit in signed integer if (zip64Block._uncompressedSize < 0) throw new InvalidDataException(SR.FieldTooBigUncompressedSize); if (zip64Block._compressedSize < 0) throw new InvalidDataException(SR.FieldTooBigCompressedSize); if (zip64Block._localHeaderOffset < 0) throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset); if (zip64Block._startDiskNumber < 0) throw new InvalidDataException(SR.FieldTooBigStartDiskNumber); return true; } } finally { if (ms != null) ms.Dispose(); } }
public static Zip64ExtraField GetAndRemoveZip64Block(List<ZipGenericExtraField> extraFields, bool readUncompressedSize, bool readCompressedSize, bool readLocalHeaderOffset, bool readStartDiskNumber) { Zip64ExtraField zip64Field = new Zip64ExtraField(); zip64Field._compressedSize = null; zip64Field._uncompressedSize = null; zip64Field._localHeaderOffset = null; zip64Field._startDiskNumber = null; List<ZipGenericExtraField> markedForDelete = new List<ZipGenericExtraField>(); bool zip64FieldFound = false; foreach (ZipGenericExtraField ef in extraFields) { if (ef.Tag == TagConstant) { markedForDelete.Add(ef); if (!zip64FieldFound) { if (TryGetZip64BlockFromGenericExtraField(ef, readUncompressedSize, readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64Field)) { zip64FieldFound = true; } } } } foreach (ZipGenericExtraField ef in markedForDelete) extraFields.Remove(ef); return zip64Field; }
// if saveExtraFieldsAndComments is false, FileComment and ExtraFields will be null // in either case, the zip64 extra field info will be incorporated into other fields public static bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header) { header = new ZipCentralDirectoryFileHeader(); if (reader.ReadUInt32() != SignatureConstant) { return(false); } header.VersionMadeBySpecification = reader.ReadByte(); header.VersionMadeByCompatibility = reader.ReadByte(); header.VersionNeededToExtract = reader.ReadUInt16(); header.GeneralPurposeBitFlag = reader.ReadUInt16(); header.CompressionMethod = reader.ReadUInt16(); header.LastModified = reader.ReadUInt32(); header.Crc32 = reader.ReadUInt32(); uint compressedSizeSmall = reader.ReadUInt32(); uint uncompressedSizeSmall = reader.ReadUInt32(); header.FilenameLength = reader.ReadUInt16(); header.ExtraFieldLength = reader.ReadUInt16(); header.FileCommentLength = reader.ReadUInt16(); ushort diskNumberStartSmall = reader.ReadUInt16(); header.InternalFileAttributes = reader.ReadUInt16(); header.ExternalFileAttributes = reader.ReadUInt32(); uint relativeOffsetOfLocalHeaderSmall = reader.ReadUInt32(); header.Filename = reader.ReadBytes(header.FilenameLength); bool uncompressedSizeInZip64 = uncompressedSizeSmall == ZipHelper.Mask32Bit; bool compressedSizeInZip64 = compressedSizeSmall == ZipHelper.Mask32Bit; bool relativeOffsetInZip64 = relativeOffsetOfLocalHeaderSmall == ZipHelper.Mask32Bit; bool diskNumberStartInZip64 = diskNumberStartSmall == ZipHelper.Mask16Bit; Zip64ExtraField zip64; long endExtraFields = reader.BaseStream.Position + header.ExtraFieldLength; using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, header.ExtraFieldLength)) { if (saveExtraFieldsAndComments) { header.ExtraFields = ZipGenericExtraField.ParseExtraField(str); zip64 = Zip64ExtraField.GetAndRemoveZip64Block(header.ExtraFields, uncompressedSizeInZip64, compressedSizeInZip64, relativeOffsetInZip64, diskNumberStartInZip64); } else { header.ExtraFields = null; zip64 = Zip64ExtraField.GetJustZip64Block(str, uncompressedSizeInZip64, compressedSizeInZip64, relativeOffsetInZip64, diskNumberStartInZip64); } } // There are zip files that have malformed ExtraField blocks in which GetJustZip64Block() silently bails out without reading all the way to the end // of the ExtraField block. Thus we must force the stream's position to the proper place. reader.BaseStream.AdvanceToPosition(endExtraFields); if (saveExtraFieldsAndComments) { header.FileComment = reader.ReadBytes(header.FileCommentLength); } else { reader.BaseStream.Position += header.FileCommentLength; header.FileComment = null; } header.UncompressedSize = zip64.UncompressedSize == null ? uncompressedSizeSmall : zip64.UncompressedSize.Value; header.CompressedSize = zip64.CompressedSize == null ? compressedSizeSmall : zip64.CompressedSize.Value; header.RelativeOffsetOfLocalHeader = zip64.LocalHeaderOffset == null ? relativeOffsetOfLocalHeaderSmall : zip64.LocalHeaderOffset.Value; header.DiskNumberStart = zip64.StartDiskNumber == null ? diskNumberStartSmall : zip64.StartDiskNumber.Value; return(true); }
public static bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header) { Zip64ExtraField justZip64Block; long? uncompressedSize; long value; long num; long value1; header = new ZipCentralDirectoryFileHeader(); if (reader.ReadUInt32() != 33639248) { return(false); } header.VersionMadeBy = reader.ReadUInt16(); header.VersionNeededToExtract = reader.ReadUInt16(); header.GeneralPurposeBitFlag = reader.ReadUInt16(); header.CompressionMethod = reader.ReadUInt16(); header.LastModified = reader.ReadUInt32(); header.Crc32 = reader.ReadUInt32(); uint num1 = reader.ReadUInt32(); uint num2 = reader.ReadUInt32(); header.FilenameLength = reader.ReadUInt16(); header.ExtraFieldLength = reader.ReadUInt16(); header.FileCommentLength = reader.ReadUInt16(); ushort num3 = reader.ReadUInt16(); header.InternalFileAttributes = reader.ReadUInt16(); header.ExternalFileAttributes = reader.ReadUInt32(); uint num4 = reader.ReadUInt32(); header.Filename = reader.ReadBytes((int)header.FilenameLength); bool flag = num2 == -1; bool flag1 = num1 == -1; bool flag2 = num4 == -1; bool flag3 = num3 == 65535; long position = (long)(reader.BaseStream.Position + (ulong)header.ExtraFieldLength); using (Stream subReadStream = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, (long)header.ExtraFieldLength)) { if (!saveExtraFieldsAndComments) { header.ExtraFields = null; justZip64Block = Zip64ExtraField.GetJustZip64Block(subReadStream, flag, flag1, flag2, flag3); } else { header.ExtraFields = ZipGenericExtraField.ParseExtraField(subReadStream); justZip64Block = Zip64ExtraField.GetAndRemoveZip64Block(header.ExtraFields, flag, flag1, flag2, flag3); } } reader.BaseStream.AdvanceToPosition(position); if (!saveExtraFieldsAndComments) { Stream baseStream = reader.BaseStream; baseStream.Position = (long)(baseStream.Position + (ulong)header.FileCommentLength); header.FileComment = null; } else { header.FileComment = reader.ReadBytes((int)header.FileCommentLength); } if (!justZip64Block.UncompressedSize.HasValue) { value = (long)((ulong)num2); } else { uncompressedSize = justZip64Block.UncompressedSize; value = uncompressedSize.Value; } header.UncompressedSize = value; if (!justZip64Block.CompressedSize.HasValue) { num = (long)((ulong)num1); } else { uncompressedSize = justZip64Block.CompressedSize; num = uncompressedSize.Value; } header.CompressedSize = num; if (!justZip64Block.LocalHeaderOffset.HasValue) { value1 = (long)((ulong)num4); } else { uncompressedSize = justZip64Block.LocalHeaderOffset; value1 = uncompressedSize.Value; } header.RelativeOffsetOfLocalHeader = value1; header.DiskNumberStart = (!justZip64Block.StartDiskNumber.HasValue ? (int)num3 : justZip64Block.StartDiskNumber.Value); return(true); }