Пример #1
0
        //Initializes, attaches it to archive
        internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
        {
            _archive = archive;

            _originallyInArchive = true;

            _diskNumberStart = cd.DiskNumberStart;
            _versionToExtract = (ZipVersionNeededValues)cd.VersionNeededToExtract;
            _generalPurposeBitFlag = (BitFlagValues)cd.GeneralPurposeBitFlag;
            CompressionMethod = (CompressionMethodValues)cd.CompressionMethod;
            _lastModified = new DateTimeOffset(ZipHelper.DosTimeToDateTime(cd.LastModified));
            _compressedSize = cd.CompressedSize;
            _uncompressedSize = cd.UncompressedSize;
            _offsetOfLocalHeader = cd.RelativeOffsetOfLocalHeader;
            /* we don't know this yet: should be _offsetOfLocalHeader + 30 + _storedEntryNameBytes.Length + extrafieldlength
                * but entryname/extra length could be different in LH
                */
            _storedOffsetOfCompressedData = null;
            _crc32 = cd.Crc32;

            _compressedBytes = null;
            _storedUncompressedData = null;
            _currentlyOpenForWrite = false;
            _everOpenedForWrite = false;
            _outstandingWriteStream = null;

            FullName = DecodeEntryName(cd.Filename);

            _lhUnknownExtraFields = null;
            //the cd should have these as null if we aren't in Update mode
            _cdUnknownExtraFields = cd.ExtraFields;
            _fileComment = cd.FileComment;

            _compressionLevel = null;
        }
Пример #2
0
        // Initializes, attaches it to archive
        internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
        {
            Archive = archive;

            _diskNumberStart       = cd.DiskNumberStart;
            _generalPurposeBitFlag = (BitFlagValues)cd.GeneralPurposeBitFlag;
            _compressionMethod     = (CompressionMethodValues)cd.CompressionMethod;

            // Leave this as a uint and let the caller convert it if it wants (perf optimization)
            LastWriteTime = cd.LastModified;

            CompressedLength     = cd.CompressedSize;
            Length               = cd.UncompressedSize;
            ExternalAttributes   = (int)cd.ExternalFileAttributes;
            _offsetOfLocalHeader = cd.RelativeOffsetOfLocalHeader;

            // we don't know this yet: should be _offsetOfLocalHeader + 30 + _storedEntryNameBytes.Length + extrafieldlength
            // but entryname/extra length could be different in LH
            _storedOffsetOfCompressedData = null;

            Crc32 = cd.Crc32;

            // Sacrifice a slight amount of time for safety. Zips entry names are emphatically NOT supposed to
            // have backslashes according to the spec, but they might anyway, so normalize them all to forward slashes.
            FullName = DecodeEntryName(cd.Filename)?.Replace('\\', '/') ?? throw new ArgumentNullException(nameof(FullName));
            Name     = ParseFileName(FullName, (ZipVersionMadeByPlatform)cd.VersionMadeByCompatibility);
        }
Пример #3
0
        // Initializes, attaches it to archive
        internal ZipArchiveEntry(ZipArchiveFast archive, ZipCentralDirectoryFileHeader cd)
        {
            Archive = archive;

            _diskNumberStart       = cd.DiskNumberStart;
            _generalPurposeBitFlag = (BitFlagValues)cd.GeneralPurposeBitFlag;
            _compressionMethod     = (CompressionMethodValues)cd.CompressionMethod;

            // Leave this as a uint and let the caller convert it if it wants (perf optimization)
            LastWriteTime = cd.LastModified;

            CompressedLength     = cd.CompressedSize;
            Length               = cd.UncompressedSize;
            _offsetOfLocalHeader = cd.RelativeOffsetOfLocalHeader;

            // we don't know this yet: should be _offsetOfLocalHeader + 30 + _storedEntryNameBytes.Length + extrafieldlength
            // but entryname/extra length could be different in LH
            _storedOffsetOfCompressedData = null;

            // Sacrifice a slight amount of time for safety. Zips entry names are emphatically NOT supposed to
            // have backslashes according to the spec, but they might anyway, so normalize them all to forward slashes.
            FullName = DecodeEntryName(cd.Filename).Replace('\\', '/');
            // Lazy-load Name so we don't preemptively do a ton of Substring() calls when we don't need to.
            _versionMadeByCompatibility = (ZipVersionMadeByPlatform)cd.VersionMadeByCompatibility;
        }
Пример #4
0
 internal ZipArchiveEntry(ZipArchive archive, string entryName)
 {
     _archive                      = archive;
     _originallyInArchive          = false;
     _diskNumberStart              = 0;
     _versionToExtract             = ZipVersionNeededValues.Default;
     _generalPurposeBitFlag        = 0;
     CompressionMethod             = CompressionMethodValues.Deflate;
     _lastModified                 = DateTimeOffset.Now;
     _compressedSize               = 0L;
     _uncompressedSize             = 0L;
     _offsetOfLocalHeader          = 0L;
     _storedOffsetOfCompressedData = null;
     _crc32                  = 0;
     _compressedBytes        = null;
     _storedUncompressedData = null;
     _currentlyOpenForWrite  = false;
     _everOpenedForWrite     = false;
     _outstandingWriteStream = null;
     FullName                = entryName;
     _cdUnknownExtraFields   = null;
     _lhUnknownExtraFields   = null;
     _fileComment            = null;
     _compressionLevel       = null;
     if (_storedEntryNameBytes.Length > 0xffff)
     {
         throw new ArgumentException(Messages.EntryNamesTooLong);
     }
     if (_archive.Mode == ZipArchiveMode.Create)
     {
         _archive.AcquireArchiveStream(this);
     }
 }
Пример #5
0
 internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
 {
     _archive                      = archive;
     _originallyInArchive          = true;
     _diskNumberStart              = cd.DiskNumberStart;
     _versionToExtract             = (ZipVersionNeededValues)cd.VersionNeededToExtract;
     _generalPurposeBitFlag        = (BitFlagValues)cd.GeneralPurposeBitFlag;
     CompressionMethod             = (CompressionMethodValues)cd.CompressionMethod;
     _lastModified                 = new DateTimeOffset(ZipHelper.DosTimeToDateTime(cd.LastModified));
     _compressedSize               = cd.CompressedSize;
     _uncompressedSize             = cd.UncompressedSize;
     _offsetOfLocalHeader          = cd.RelativeOffsetOfLocalHeader;
     _storedOffsetOfCompressedData = null;
     _crc32                  = cd.Crc32;
     _compressedBytes        = null;
     _storedUncompressedData = null;
     _currentlyOpenForWrite  = false;
     _everOpenedForWrite     = false;
     _outstandingWriteStream = null;
     FullName                = DecodeEntryName(cd.Filename);
     _lhUnknownExtraFields   = null;
     _cdUnknownExtraFields   = cd.ExtraFields;
     _fileComment            = cd.FileComment;
     _compressionLevel       = null;
 }
Пример #6
0
        // Initializes new entry
        internal ZipArchiveEntry(ZipArchive archive, string entryName)
        {
            _archive = archive;

            _originallyInArchive = false;

            _diskNumberStart            = 0;
            _versionMadeByPlatform      = CurrentZipPlatform;
            _versionMadeBySpecification = ZipVersionNeededValues.Default;
            _versionToExtract           = ZipVersionNeededValues.Default; // this must happen before following two assignment
            _generalPurposeBitFlag      = 0;
            CompressionMethod           = CompressionMethodValues.Deflate;
            _lastModified = DateTimeOffset.Now;

            _compressedSize               = 0; // we don't know these yet
            _uncompressedSize             = 0;
            _externalFileAttr             = 0;
            _offsetOfLocalHeader          = 0;
            _storedOffsetOfCompressedData = null;
            _crc32 = 0;

            _compressedBytes        = null;
            _storedUncompressedData = null;
            _currentlyOpenForWrite  = false;
            _everOpenedForWrite     = false;
            _outstandingWriteStream = null;

            FullName = entryName;

            _cdUnknownExtraFields = null;
            _lhUnknownExtraFields = null;
            _fileComment          = null;

            _compressionLevel = null;

            if (_storedEntryNameBytes.Length > ushort.MaxValue)
            {
                throw new ArgumentException();
            }

            // grab the stream if we're in create mode
            if (_archive.Mode == ZipArchiveMode.Create)
            {
                _archive.AcquireArchiveStream(this);
            }
        }
Пример #7
0
        private void WriteCrcAndSizesInLocalHeader(bool zip64HeaderUsed)
        {
            long         position = _archive.ArchiveStream.Position;
            BinaryWriter writer   = new BinaryWriter(_archive.ArchiveStream);
            bool         flag1    = SizesTooLarge();
            bool         flag     = flag1 && !zip64HeaderUsed;
            uint         num2     = flag1 ? uint.MaxValue : ((uint)_compressedSize);
            uint         num3     = flag1 ? uint.MaxValue : ((uint)_uncompressedSize);

            if (flag)
            {
                _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
                _archive.ArchiveStream.Seek(_offsetOfLocalHeader + 6L, SeekOrigin.Begin);
                writer.Write((ushort)_generalPurposeBitFlag);
            }
            _archive.ArchiveStream.Seek(_offsetOfLocalHeader + 14L, SeekOrigin.Begin);
            if (!flag)
            {
                writer.Write(_crc32);
                writer.Write(num2);
                writer.Write(num3);
            }
            else
            {
                writer.Write((uint)0);
                writer.Write((uint)0);
                writer.Write((uint)0);
            }
            if (zip64HeaderUsed)
            {
                _archive.ArchiveStream.Seek(((_offsetOfLocalHeader + 30L) + _storedEntryNameBytes.Length) + 4L, SeekOrigin.Begin);
                writer.Write(_uncompressedSize);
                writer.Write(_compressedSize);
                _archive.ArchiveStream.Seek(position, SeekOrigin.Begin);
            }
            _archive.ArchiveStream.Seek(position, SeekOrigin.Begin);
            if (flag)
            {
                writer.Write(_crc32);
                writer.Write(_compressedSize);
                writer.Write(_uncompressedSize);
            }
        }
Пример #8
0
        // Initializes, attaches it to archive
        internal ReadOnlyZipArchiveEntry(ReadOnlyZipArchive archive, ZipCentralDirectoryFileHeader cd)
        {
            _archive = archive;

            _originallyInArchive = true;

            _diskNumberStart            = cd.DiskNumberStart;
            _versionMadeByPlatform      = ( ZipVersionMadeByPlatform )cd.VersionMadeByCompatibility;
            _versionMadeBySpecification = ( ZipVersionNeededValues )cd.VersionMadeBySpecification;
            _versionToExtract           = ( ZipVersionNeededValues )cd.VersionNeededToExtract;
            _generalPurposeBitFlag      = ( BitFlagValues )cd.GeneralPurposeBitFlag;
            CompressionMethod           = ( CompressionMethodValues )cd.CompressionMethod;
            _lastModified        = new DateTimeOffset(ZipHelper.DosTimeToDateTime(cd.LastModified));
            _compressedSize      = cd.CompressedSize;
            _uncompressedSize    = cd.UncompressedSize;
            _externalFileAttr    = cd.ExternalFileAttributes;
            _offsetOfLocalHeader = cd.RelativeOffsetOfLocalHeader;
            // we don't know this yet: should be _offsetOfLocalHeader + 30 + _storedEntryNameBytes.Length + extrafieldlength
            // but entryname/extra length could be different in LH
            _storedOffsetOfCompressedData = null;
            _crc32 = cd.Crc32;

            _compressedBytes        = null;
            _storedUncompressedData = null;
            _currentlyOpenForWrite  = false;
            _everOpenedForWrite     = false;
            _outstandingWriteStream = null;

            FullName = DecodeEntryName(cd.Filename);

            _lhUnknownExtraFields = null;
            // the cd should have these as null if we aren't in Update mode
            _cdUnknownExtraFields = cd.ExtraFields;
            _fileComment          = cd.FileComment;

            _compressionLevel = null;
        }
Пример #9
0
        /* Using _offsetOfLocalHeader, seeks back to where CRC and sizes should be in the header,
         * writes them, then seeks back to where you started
         * Assumes that the stream is currently at the end of the data
        */
        private void WriteCrcAndSizesInLocalHeader(Boolean zip64HeaderUsed)
        {
            Int64 finalPosition = _archive.ArchiveStream.Position;
            BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream);

            Boolean zip64Needed = SizesTooLarge()
#if DEBUG_FORCE_ZIP64
 || _archive._forceZip64
#endif
;
            Boolean pretendStreaming = zip64Needed && !zip64HeaderUsed;

            UInt32 compressedSizeTruncated = zip64Needed ? ZipHelper.Mask32Bit : (UInt32)_compressedSize;
            UInt32 uncompressedSizeTruncated = zip64Needed ? ZipHelper.Mask32Bit : (UInt32)_uncompressedSize;

            /* first step is, if we need zip64, but didn't allocate it, pretend we did a stream write, because
             * we can't go back and give ourselves the space that the extra field needs.
             * we do this by setting the correct property in the bit flag */
            if (pretendStreaming)
            {
                _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;

                _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToBitFlagFromHeaderStart,
                                            SeekOrigin.Begin);
                writer.Write((UInt16)_generalPurposeBitFlag);
            }

            /* next step is fill out the 32-bit size values in the normal header. we can't assume that
             * they are correct. we also write the CRC */
            _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToCrcFromHeaderStart,
                                            SeekOrigin.Begin);
            if (!pretendStreaming)
            {
                writer.Write(_crc32);
                writer.Write(compressedSizeTruncated);
                writer.Write(uncompressedSizeTruncated);
            }
            else //but if we are pretending to stream, we want to fill in with zeroes
            {
                writer.Write((UInt32)0);
                writer.Write((UInt32)0);
                writer.Write((UInt32)0);
            }

            /* next step: if we wrote the 64 bit header initially, a different implementation might
             * try to read it, even if the 32-bit size values aren't masked. thus, we should always put the
             * correct size information in there. note that order of uncomp/comp is switched, and these are
             * 64-bit values
             * also, note that in order for this to be correct, we have to insure that the zip64 extra field
             * is always the first extra field that is written */
            if (zip64HeaderUsed)
            {
                _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.SizeOfLocalHeader
                                            + _storedEntryNameBytes.Length + Zip64ExtraField.OffsetToFirstField,
                                            SeekOrigin.Begin);
                writer.Write(_uncompressedSize);
                writer.Write(_compressedSize);

                _archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);
            }

            // now go to the where we were. assume that this is the end of the data
            _archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);

            /* if we are pretending we did a stream write, we want to write the data descriptor out
             * the data descriptor can have 32-bit sizes or 64-bit sizes. In this case, we always use
             * 64-bit sizes */
            if (pretendStreaming)
            {
                writer.Write(_crc32);
                writer.Write(_compressedSize);
                writer.Write(_uncompressedSize);
            }
        }
Пример #10
0
        //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;
        }
Пример #11
0
        //Initializes new entry
        internal ZipArchiveEntry(ZipArchive archive, String entryName)
        {
            _archive = archive;

            _originallyInArchive = false;

            _diskNumberStart = 0;
            _versionMadeByPlatform = CurrentZipPlatform;
            _versionMadeBySpecification = ZipVersionNeededValues.Default;
            _versionToExtract = ZipVersionNeededValues.Default; //this must happen before following two assignment
            _generalPurposeBitFlag = 0;
            CompressionMethod = CompressionMethodValues.Deflate;
            _lastModified = DateTimeOffset.Now;

            _compressedSize = 0; //we don't know these yet
            _uncompressedSize = 0;
            _offsetOfLocalHeader = 0;
            _storedOffsetOfCompressedData = null;
            _crc32 = 0;

            _compressedBytes = null;
            _storedUncompressedData = null;
            _currentlyOpenForWrite = false;
            _everOpenedForWrite = false;
            _outstandingWriteStream = null;

            FullName = entryName;

            _cdUnknownExtraFields = null;
            _lhUnknownExtraFields = null;
            _fileComment = null;

            _compressionLevel = null;

            if (_storedEntryNameBytes.Length > UInt16.MaxValue)
                throw new ArgumentException(SR.EntryNamesTooLong);

            //grab the stream if we're in create mode
            if (_archive.Mode == ZipArchiveMode.Create)
            {
                _archive.AcquireArchiveStream(this);
            }
        }
Пример #12
0
 /// <summary>
 /// Helper function used to set and reset bits in the publicOptions bit-field.
 /// </summary>
 private void SetOptionField(BitFlagValues mask, bool value)
 {
     EnumBits = value ? EnumBits |= mask : EnumBits &= ~mask;
 }
Пример #13
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="index"></param>
 /// <returns></returns>
 public bool this[BitFlagValues index]
 {
     get { return((EnumBits & index) != 0); }
     set { EnumBits = value ? EnumBits |= index : EnumBits &= ~index; }
 }
Пример #14
0
        // Using _offsetOfLocalHeader, seeks back to where CRC and sizes should be in the header,
        // writes them, then seeks back to where you started
        // Assumes that the stream is currently at the end of the data
        private void WriteCrcAndSizesInLocalHeader(bool zip64HeaderUsed)
        {
            long         finalPosition = _archive.ArchiveStream.Position;
            BinaryWriter writer        = new BinaryWriter(_archive.ArchiveStream);

            bool zip64Needed = SizesTooLarge()
#if DEBUG_FORCE_ZIP64
                               || _archive._forceZip64
#endif
            ;

            bool pretendStreaming = zip64Needed && !zip64HeaderUsed;

            uint compressedSizeTruncated   = zip64Needed ? ZipHelper.Mask32Bit : (uint)_compressedSize;
            uint uncompressedSizeTruncated = zip64Needed ? ZipHelper.Mask32Bit : (uint)_uncompressedSize;

            // first step is, if we need zip64, but didn't allocate it, pretend we did a stream write, because
            // we can't go back and give ourselves the space that the extra field needs.
            // we do this by setting the correct property in the bit flag
            if (pretendStreaming)
            {
                _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;

                _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToBitFlagFromHeaderStart,
                                            SeekOrigin.Begin);
                writer.Write((ushort)_generalPurposeBitFlag);
            }

            // next step is fill out the 32-bit size values in the normal header. we can't assume that
            // they are correct. we also write the CRC
            _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToCrcFromHeaderStart,
                                        SeekOrigin.Begin);
            if (!pretendStreaming)
            {
                writer.Write(_crc32);
                writer.Write(compressedSizeTruncated);
                writer.Write(uncompressedSizeTruncated);
            }
            else // but if we are pretending to stream, we want to fill in with zeroes
            {
                writer.Write((uint)0);
                writer.Write((uint)0);
                writer.Write((uint)0);
            }

            // next step: if we wrote the 64 bit header initially, a different implementation might
            // try to read it, even if the 32-bit size values aren't masked. thus, we should always put the
            // correct size information in there. note that order of uncomp/comp is switched, and these are
            // 64-bit values
            // also, note that in order for this to be correct, we have to insure that the zip64 extra field
            // is always the first extra field that is written
            if (zip64HeaderUsed)
            {
                _archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.SizeOfLocalHeader
                                            + _storedEntryNameBytes.Length + Zip64ExtraField.OffsetToFirstField,
                                            SeekOrigin.Begin);
                writer.Write(_uncompressedSize);
                writer.Write(_compressedSize);

                _archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);
            }

            // now go to the where we were. assume that this is the end of the data
            _archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);

            // if we are pretending we did a stream write, we want to write the data descriptor out
            // the data descriptor can have 32-bit sizes or 64-bit sizes. In this case, we always use
            // 64-bit sizes
            if (pretendStreaming)
            {
                writer.Write(_crc32);
                writer.Write(_compressedSize);
                writer.Write(_uncompressedSize);
            }
        }
Пример #15
0
        // 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);
        }
Пример #16
0
        private bool WriteLocalFileHeader(bool isEmptyFile)
        {
            uint            maxValue;
            uint            num2;
            ushort          num4;
            BinaryWriter    writer = new BinaryWriter(_archive.ArchiveStream);
            Zip64ExtraField field  = new Zip64ExtraField();
            bool            flag   = false;

            if (isEmptyFile)
            {
                CompressionMethod = CompressionMethodValues.Stored;
                maxValue          = 0;
                num2 = 0;
            }
            else if (((_archive.Mode == ZipArchiveMode.Create) && !_archive.ArchiveStream.CanSeek) && !isEmptyFile)
            {
                _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
                flag     = false;
                maxValue = 0;
                num2     = 0;
            }
            else if (SizesTooLarge())
            {
                flag                   = true;
                maxValue               = uint.MaxValue;
                num2                   = uint.MaxValue;
                field.CompressedSize   = new long?(_compressedSize);
                field.UncompressedSize = new long?(_uncompressedSize);
                VersionToExtractAtLeast(ZipVersionNeededValues.Zip64);
            }
            else
            {
                flag     = false;
                maxValue = (uint)_compressedSize;
                num2     = (uint)_uncompressedSize;
            }
            _offsetOfLocalHeader = writer.BaseStream.Position;
            int num3 = (flag ? field.TotalSize : 0) + ((_lhUnknownExtraFields != null) ? ZipGenericExtraField.TotalSize(_lhUnknownExtraFields) : 0);

            if (num3 > 0xffff)
            {
                num4 = flag ? field.TotalSize : ((ushort)0);
                _lhUnknownExtraFields = null;
            }
            else
            {
                num4 = (ushort)num3;
            }
            writer.Write((uint)0x4034b50);
            writer.Write((ushort)_versionToExtract);
            writer.Write((ushort)_generalPurposeBitFlag);
            writer.Write((ushort)CompressionMethod);
            writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime));
            writer.Write(_crc32);
            writer.Write(maxValue);
            writer.Write(num2);
            writer.Write((ushort)_storedEntryNameBytes.Length);
            writer.Write(num4);
            writer.Write(_storedEntryNameBytes);
            if (flag)
            {
                field.WriteBlock(_archive.ArchiveStream);
            }
            if (_lhUnknownExtraFields != null)
            {
                ZipGenericExtraField.WriteAllBlocks(_lhUnknownExtraFields, _archive.ArchiveStream);
            }
            return(flag);
        }