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