Example #1
0
        void WriteLocalEntryHeader(ZipUpdate update)
        {
            ZipEntry entry = update.OutEntry;

            // TODO: Local offset will require adjusting for multi-disk zip files.
            entry.Offset = baseStream_.Position;

            // TODO: Need to clear any entry flags that dont make sense or throw an exception here.
            if (update.Command != UpdateCommand.Copy) {
                if (entry.CompressionMethod == CompressionMethod.Deflated) {
                    if (entry.Size == 0) {
                        // No need to compress - no data.
                        entry.CompressedSize = entry.Size;
                        entry.Crc = 0;
                        entry.CompressionMethod = CompressionMethod.Stored;
                    }
                }
                else if (entry.CompressionMethod == CompressionMethod.Stored) {
                    entry.Flags &= ~(int)GeneralBitFlags.Descriptor;
                }

                if (HaveKeys) {
                    entry.IsCrypted = true;
                    if (entry.Crc < 0) {
                        entry.Flags |= (int)GeneralBitFlags.Descriptor;
                    }
                }
                else {
                    entry.IsCrypted = false;
                }

                switch (useZip64_) {
                    case UseZip64.Dynamic:
                        if (entry.Size < 0) {
                            entry.ForceZip64();
                        }
                        break;

                    case UseZip64.On:
                        entry.ForceZip64();
                        break;

                    case UseZip64.Off:
                        // Do nothing.  The entry itself may be using Zip64 independantly.
                        break;
                }
            }

            // Write the local file header
            WriteLEInt(ZipConstants.LocalHeaderSignature);

            WriteLEShort(entry.Version);
            WriteLEShort(entry.Flags);

            WriteLEShort((byte)entry.CompressionMethod);
            WriteLEInt(( int )entry.DosTime);

            if ( !entry.HasCrc ) {
                // Note patch address for updating CRC later.
                update.CrcPatchOffset = baseStream_.Position;
                WriteLEInt(( int )0);
            }
            else {
                WriteLEInt(unchecked(( int )entry.Crc));
            }

            if (entry.LocalHeaderRequiresZip64) {
                WriteLEInt(-1);
                WriteLEInt(-1);
            }
            else {
                if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) {
                    update.SizePatchOffset = baseStream_.Position;
                }

                WriteLEInt(( int )entry.CompressedSize);
                WriteLEInt(( int )entry.Size);
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if ( entry.LocalHeaderRequiresZip64 ) {
                ed.StartNewEntry();

                // Local entry header always includes size and compressed size.
                // NOTE the order of these fields is reversed when compared to the normal headers!
                ed.AddLeLong(entry.Size);
                ed.AddLeLong(entry.CompressedSize);
                ed.AddNewEntry(1);
            }
            else {
                ed.Delete(1);
            }

            entry.ExtraData = ed.GetEntryData();

            WriteLEShort(name.Length);
            WriteLEShort(entry.ExtraData.Length);

            if ( name.Length > 0 ) {
                baseStream_.Write(name, 0, name.Length);
            }

            if ( entry.LocalHeaderRequiresZip64 ) {
                update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex;
            }

            if ( entry.ExtraData.Length > 0 ) {
                baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length);
            }
        }
Example #2
0
        // Write the local file header
        // TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage
        void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData)
        {
            CompressionMethod method = entry.CompressionMethod;
            bool headerInfoAvailable = true; // How to get this?
            bool patchEntryHeader = false;

            WriteLEInt(ZipConstants.LocalHeaderSignature);

            WriteLEShort(entry.Version);
            WriteLEShort(entry.Flags);
            WriteLEShort((byte)method);
            WriteLEInt((int)entry.DosTime);

            if (headerInfoAvailable == true) {
                WriteLEInt((int)entry.Crc);
                if ( entry.LocalHeaderRequiresZip64 ) {
                    WriteLEInt(-1);
                    WriteLEInt(-1);
                }
                else {
                    WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize);
                    WriteLEInt((int)entry.Size);
                }
            } else {
                if (patchData != null) {
                    patchData.CrcPatchOffset = stream_.Position;
                }
                WriteLEInt(0);	// Crc

                if ( patchData != null ) {
                    patchData.SizePatchOffset = stream_.Position;
                }

                // For local header both sizes appear in Zip64 Extended Information
                if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
                    WriteLEInt(-1);
                    WriteLEInt(-1);
                }
                else {
                    WriteLEInt(0);	// Compressed size
                    WriteLEInt(0);	// Uncompressed size
                }
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) {
                ed.StartNewEntry();
                if (headerInfoAvailable) {
                    ed.AddLeLong(entry.Size);
                    ed.AddLeLong(entry.CompressedSize);
                }
                else {
                    ed.AddLeLong(-1);
                    ed.AddLeLong(-1);
                }
                ed.AddNewEntry(1);

                if ( patchData != null ) {
                    patchData.SizePatchOffset = ed.CurrentReadIndex;
                }
            }
            else {
                ed.Delete(1);
            }

            byte[] extra = ed.GetEntryData();

            WriteLEShort(name.Length);
            WriteLEShort(extra.Length);

            if ( name.Length > 0 ) {
                stream_.Write(name, 0, name.Length);
            }

            if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
                patchData.SizePatchOffset += stream_.Position;
            }

            if ( extra.Length > 0 ) {
                stream_.Write(extra, 0, extra.Length);
            }
        }
Example #3
0
        int WriteCentralDirectoryHeader(ZipEntry entry)
        {
            // Write the central file header
            WriteLEInt(ZipConstants.CentralHeaderSignature);

            // Version made by
            WriteLEShort(ZipConstants.VersionMadeBy);

            // Version required to extract
            WriteLEShort(entry.Version);

            WriteLEShort(entry.Flags);

            unchecked {
                WriteLEShort((byte)entry.CompressionMethod);
                WriteLEInt((int)entry.DosTime);
                WriteLEInt((int)entry.Crc);
            }

            if ( (entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff) ) {
                WriteLEInt(-1);
            }
            else {
                WriteLEInt((int)(entry.CompressedSize & 0xffffffff));
            }

            if ( (entry.IsZip64Forced()) || (entry.Size >= 0xffffffff) ) {
                WriteLEInt(-1);
            }
            else {
                WriteLEInt((int)entry.Size);
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            WriteLEShort(name.Length);

            // Central header extra data is different to local header version so regenerate.
            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if ( entry.CentralHeaderRequiresZip64 ) {
                ed.StartNewEntry();

                if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) )
                {
                    ed.AddLeLong(entry.Size);
                }

                if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) )
                {
                    ed.AddLeLong(entry.CompressedSize);
                }

                if ( entry.Offset >= 0xffffffff ) {
                    ed.AddLeLong(entry.Offset);
                }

                // Number of disk on which this file starts isnt supported and is never written here.
                ed.AddNewEntry(1);
            }
            else {
                // Should have already be done when local header was added.
                ed.Delete(1);
            }

            byte[] centralExtraData = ed.GetEntryData();

            WriteLEShort(centralExtraData.Length);
            WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0);

            WriteLEShort(0);	// disk number
            WriteLEShort(0);	// internal file attributes

            // External file attributes...
            if ( entry.ExternalFileAttributes != -1 ) {
                WriteLEInt(entry.ExternalFileAttributes);
            }
            else {
                if ( entry.IsDirectory ) {
                    WriteLEUint(16);
                }
                else {
                    WriteLEUint(0);
                }
            }

            if ( entry.Offset >= 0xffffffff ) {
                WriteLEUint(0xffffffff);
            }
            else {
                WriteLEUint((uint)(int)entry.Offset);
            }

            if ( name.Length > 0 ) {
                baseStream_.Write(name, 0, name.Length);
            }

            if ( centralExtraData.Length > 0 ) {
                baseStream_.Write(centralExtraData, 0, centralExtraData.Length);
            }

            byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0];

            if ( rawComment.Length > 0 ) {
                baseStream_.Write(rawComment, 0, rawComment.Length);
            }

            return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length;
        }