Example #1
0
        /// <summary>
        /// Writes the header of the file with the writer.
        /// </summary>
        /// <param name="writer"> The writer. </param>
        /// <param name="entry"> The entry. </param>
        /// <param name="isCentralFileHeader"> Determines whether header is central file header or not (local). </param>
        private void WriteFileHeader(IByteArrayWriter writer, ZipWriteOnlyStorerEntry entry, bool isCentralFileHeader)
        {
            if (isCentralFileHeader)
            {
                writer.WriteBytes(centralDirectoryFileHeaderSignatureBytes); // 4 bytes, central directory file header signature
                writer.WriteBytes(23, 0xB);                                  // 2 bytes, version made by
            }
            else
            {
                writer.WriteBytes(localFileHeaderSignatureBytes); // 4 bytes, local file header signature
            }

            writer.WriteBytes(versionToExtractBytes);          // 2 bytes, version needed to extract (minimum)
            writer.WriteBytes(gpbg8Bytes);                     // 2 bytes, general purpose bit flag
            writer.WriteBytes(entry.CompressionMethodAsBytes); // 2 bytes, compression method
            writer.WriteBytes(entry.ModifyTimeAsBytes);        // 2+2 bytes, file last modification time and date
            writer.WriteBytes(entry.CRC32AsBytes);             // 4 bytes, CRC-32
            writer.WriteBytes(entry.CompressedSizeAsBytes);    // 4 bytes, compressed size
            writer.WriteBytes(entry.SizeAsBytes);              // 4 bytes, uncompressed size
            writer.WriteBytes(entry.PathLengthAsBytes);        // 2 bytes, file name length

            if (this.isZip64)
            {
                writer.WriteBytes(thirtyTwo2Bytes); // 2 bytes, extra field length = 32
            }
            else
            {
                writer.WriteBytes(zero2Bytes); // 2 bytes, extra field length = 32
            }

            if (isCentralFileHeader)
            {
                writer.WriteBytes(entry.CommentLengthAsBytes); // 2 bytes, file comment length
                writer.WriteBytes(zero4Bytes);                 // 2+2=4 bytes, disk number where file starts (disk=0), internal file attributes
                writer.WriteBytes(externalAttributesBytes);    // 4 bytes, External file attributes
                writer.WriteBytes(entry.HeaderOffsetAsBytes);  // 4 bytes, relative offset of header
            }

            writer.WriteBytes(entry.PathAsBytes); // variable size, file name

            if (this.isZip64)
            {
                writer.WriteBytes(zip64ExtraBlockTagSignatureBytes); // 2 bytes, tag for the extra block (ZIP64 Extended Information Extra Field)
                writer.WriteBytes(thirtyTwo2Bytes);                  // 2 bytes, size of the extra block
                writer.WriteBytes(zero4Bytes);
                writer.WriteBytes(entry.SizeZip64AsBytes);           // 8 bytes, uncompressed size
                writer.WriteBytes(zero4Bytes);
                writer.WriteBytes(entry.CompressedSizeZip64AsBytes); // 8 bytes, compressed size
                writer.WriteBytes(zero4Bytes);
                writer.WriteBytes(entry.HeaderOffsetZip64AsBytes);   // 8 bytes, compressed size
                writer.WriteBytes(zero4Bytes);                       // 4 bytes, disk number where file starts (disk=0)
            }

            if (isCentralFileHeader)
            {
                writer.WriteBytes(entry.CommentAsBytes); // variable size, file comment
            }
        }
Example #2
0
        /// <inheritdoc/>
        public IDataStorerEntry Add(string path, params byte[] data)
        {
            Validation.NotNull("Path", path);
            Validation.NotNull("Data", data);

            string normalizedPath = path.Replace('\\', '/');

            int pos = normalizedPath.IndexOf(':');

            if (pos >= 0)
            {
                normalizedPath = normalizedPath.Remove(0, pos + 1);
            }

            normalizedPath = normalizedPath.Trim('/');

            int uncompressedLength = data.Length;
            int compressedLength;

            byte[]            compressedData;
            CompressionMethod compressionMethod;

            if (this.enableCompression)
            {
                Deflater deflater = new Deflater(Deflater.DEFLATED);
                deflater.SetInput(data, 0, uncompressedLength);
                deflater.Finish();

                compressedData   = new byte[uncompressedLength];
                compressedLength = deflater.Deflate(compressedData, 0, uncompressedLength);
                if (deflater.IsFinished && compressedLength <= uncompressedLength)
                {
                    // Use deflate
                    compressionMethod = CompressionMethod.Deflate;
                }
                else
                {
                    // Force to store
                    compressedData    = data;
                    compressedLength  = uncompressedLength;
                    compressionMethod = CompressionMethod.Store;
                }
            }
            else
            {
                // Only store
                compressedData    = data;
                compressedLength  = uncompressedLength;
                compressionMethod = CompressionMethod.Store;
            }

            uint uncompressedSize = (uint)uncompressedLength;
            uint compressedSize   = (uint)compressedLength;
            uint crc32            = CRC32.Calculate(data);
            uint headerOffset     = (uint)this.zipFileWriter.Position;

            ZipWriteOnlyStorerEntry fileEntry = new ZipWriteOnlyStorerEntry(
                normalizedPath,
                uncompressedSize,
                compressionMethod,
                compressedSize,
                headerOffset,
                crc32,
                DateTime.Now,
                comment ?? ""
                );

            this.WriteFileHeader(this.zipFileWriter, fileEntry, false);

            this.zipFileWriter.WriteBytes(compressedData, 0, compressedLength);
            this.entries.AddLast(fileEntry);

            return(fileEntry);
        }