private void WriteLocalEntryHeader(ZipUpdate update) { ZipEntry outEntry = update.OutEntry; outEntry.Offset = baseStream_.Position; if (update.Command != UpdateCommand.Copy) { if (outEntry.CompressionMethod == CompressionMethod.Deflated) { if (outEntry.Size == 0L) { outEntry.CompressedSize = outEntry.Size; outEntry.Crc = 0L; outEntry.CompressionMethod = CompressionMethod.Stored; } } else if (outEntry.CompressionMethod == CompressionMethod.Stored) { outEntry.Flags &= -9; } if (HaveKeys) { outEntry.IsCrypted = true; if (outEntry.Crc < 0L) { outEntry.Flags |= 8; } } else { outEntry.IsCrypted = false; } switch (useZip64_) { case UseZip64.On: outEntry.ForceZip64(); break; case UseZip64.Dynamic: if (outEntry.Size < 0L) { outEntry.ForceZip64(); } break; } } WriteLEInt(0x4034b50); WriteLEShort(outEntry.Version); WriteLEShort(outEntry.Flags); WriteLEShort((byte)outEntry.CompressionMethod); WriteLEInt((int)outEntry.DosTime); if (!outEntry.HasCrc) { update.CrcPatchOffset = baseStream_.Position; WriteLEInt(0); } else { WriteLEInt((int)outEntry.Crc); } if (outEntry.LocalHeaderRequiresZip64) { WriteLEInt(-1); WriteLEInt(-1); } else { if ((outEntry.CompressedSize < 0L) || (outEntry.Size < 0L)) { update.SizePatchOffset = baseStream_.Position; } WriteLEInt((int)outEntry.CompressedSize); WriteLEInt((int)outEntry.Size); } byte[] buffer = ZipConstants.ConvertToArray(outEntry.Flags, outEntry.Name); if (buffer.Length > 0xffff) { throw new ZipException("Entry name too long."); } ZipExtraData data = new ZipExtraData(outEntry.ExtraData); if (outEntry.LocalHeaderRequiresZip64) { data.StartNewEntry(); data.AddLeLong(outEntry.Size); data.AddLeLong(outEntry.CompressedSize); data.AddNewEntry(1); } else { data.Delete(1); } outEntry.ExtraData = data.GetEntryData(); WriteLEShort(buffer.Length); WriteLEShort(outEntry.ExtraData.Length); if (buffer.Length > 0) { baseStream_.Write(buffer, 0, buffer.Length); } if (outEntry.LocalHeaderRequiresZip64) { if (!data.Find(1)) { throw new ZipException("Internal error cannot find extra data"); } update.SizePatchOffset = baseStream_.Position + data.CurrentReadIndex; } if (outEntry.ExtraData.Length > 0) { baseStream_.Write(outEntry.ExtraData, 0, outEntry.ExtraData.Length); } }
public void PutNextEntry(ZipEntry entry) { bool hasCrc; if (entry == null) { throw new ArgumentNullException("entry"); } if (entries == null) { throw new InvalidOperationException("ZipOutputStream was finished"); } if (curEntry != null) { CloseEntry(); } if (entries.Count == 0x7fffffff) { throw new ZipException("Too many entries for Zip file"); } CompressionMethod compressionMethod = entry.CompressionMethod; int compressionLevel = defaultCompressionLevel; entry.Flags &= 0x800; patchEntryHeader = false; if (entry.Size == 0L) { entry.CompressedSize = entry.Size; entry.Crc = 0L; compressionMethod = CompressionMethod.Stored; hasCrc = true; } else { hasCrc = (entry.Size >= 0L) && entry.HasCrc; if (compressionMethod == CompressionMethod.Stored) { if (!hasCrc) { if (!CanPatchEntries) { compressionMethod = CompressionMethod.Deflated; compressionLevel = 0; } } else { entry.CompressedSize = entry.Size; hasCrc = entry.HasCrc; } } } if (!hasCrc) { if (!CanPatchEntries) { entry.Flags |= 8; } else { patchEntryHeader = true; } } if (Password != null) { entry.IsCrypted = true; if (entry.Crc < 0L) { entry.Flags |= 8; } } entry.Offset = offset; entry.CompressionMethod = compressionMethod; curMethod = compressionMethod; sizePatchPos = -1L; if ((useZip64_ == UseZip64.On) || ((entry.Size < 0L) && (useZip64_ == UseZip64.Dynamic))) { entry.ForceZip64(); } WriteLeInt(0x4034b50); WriteLeShort(entry.Version); WriteLeShort(entry.Flags); WriteLeShort((byte)entry.CompressionMethodForHeader); WriteLeInt((int)entry.DosTime); if (hasCrc) { WriteLeInt((int)entry.Crc); if (entry.LocalHeaderRequiresZip64) { WriteLeInt(-1); WriteLeInt(-1); } else { WriteLeInt(entry.IsCrypted ? (((int)entry.CompressedSize) + 12) : ((int)entry.CompressedSize)); WriteLeInt((int)entry.Size); } } else { if (patchEntryHeader) { crcPatchPos = baseOutputStream_.Position; } WriteLeInt(0); if (patchEntryHeader) { sizePatchPos = baseOutputStream_.Position; } if (entry.LocalHeaderRequiresZip64 || patchEntryHeader) { WriteLeInt(-1); WriteLeInt(-1); } else { WriteLeInt(0); WriteLeInt(0); } } byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name); if (buffer.Length > 0xffff) { throw new ZipException("Entry name too long."); } ZipExtraData extraData = new ZipExtraData(entry.ExtraData); if (entry.LocalHeaderRequiresZip64) { extraData.StartNewEntry(); if (hasCrc) { extraData.AddLeLong(entry.Size); extraData.AddLeLong(entry.CompressedSize); } else { extraData.AddLeLong(-1L); extraData.AddLeLong(-1L); } extraData.AddNewEntry(1); if (!extraData.Find(1)) { throw new ZipException("Internal error cant find extra data"); } if (patchEntryHeader) { sizePatchPos = extraData.CurrentReadIndex; } } else { extraData.Delete(1); } if (entry.AESKeySize > 0) { AddExtraDataAES(entry, extraData); } byte[] entryData = extraData.GetEntryData(); WriteLeShort(buffer.Length); WriteLeShort(entryData.Length); if (buffer.Length > 0) { baseOutputStream_.Write(buffer, 0, buffer.Length); } if (entry.LocalHeaderRequiresZip64 && patchEntryHeader) { sizePatchPos += baseOutputStream_.Position; } if (entryData.Length > 0) { baseOutputStream_.Write(entryData, 0, entryData.Length); } offset += (30 + buffer.Length) + entryData.Length; if (entry.AESKeySize > 0) { offset += entry.AESOverheadSize; } curEntry = entry; crc.Reset(); if (compressionMethod == CompressionMethod.Deflated) { deflater_.Reset(); deflater_.SetLevel(compressionLevel); } size = 0L; if (entry.IsCrypted) { if (entry.AESKeySize > 0) { WriteAESHeader(entry); } else if (entry.Crc < 0L) { WriteEncryptionHeader(entry.DosTime << 0x10); } else { WriteEncryptionHeader(entry.Crc); } } }
private int WriteCentralDirectoryHeader(ZipEntry entry) { if (entry.CompressedSize < 0L) { throw new ZipException("Attempt to write central directory entry with unknown csize"); } if (entry.Size < 0L) { throw new ZipException("Attempt to write central directory entry with unknown size"); } if (entry.Crc < 0L) { throw new ZipException("Attempt to write central directory entry with unknown crc"); } WriteLEInt(0x2014b50); WriteLEShort(0x33); WriteLEShort(entry.Version); WriteLEShort(entry.Flags); WriteLEShort((byte)entry.CompressionMethod); WriteLEInt((int)entry.DosTime); WriteLEInt((int)entry.Crc); if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL)) { WriteLEInt(-1); } else { WriteLEInt((int)(((ulong)entry.CompressedSize) & 0xffffffffL)); } if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL)) { WriteLEInt(-1); } else { WriteLEInt((int)entry.Size); } byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name); if (buffer.Length > 0xffff) { throw new ZipException("Entry name is too long."); } WriteLEShort(buffer.Length); ZipExtraData data = new ZipExtraData(entry.ExtraData); if (entry.CentralHeaderRequiresZip64) { data.StartNewEntry(); if ((entry.Size >= 0xffffffffL) || (useZip64_ == UseZip64.On)) { data.AddLeLong(entry.Size); } if ((entry.CompressedSize >= 0xffffffffL) || (useZip64_ == UseZip64.On)) { data.AddLeLong(entry.CompressedSize); } if (entry.Offset >= 0xffffffffL) { data.AddLeLong(entry.Offset); } data.AddNewEntry(1); } else { data.Delete(1); } byte[] entryData = data.GetEntryData(); WriteLEShort(entryData.Length); WriteLEShort((entry.Comment != null) ? entry.Comment.Length : 0); WriteLEShort(0); WriteLEShort(0); if (entry.ExternalFileAttributes != -1) { WriteLEInt(entry.ExternalFileAttributes); } else if (entry.IsDirectory) { WriteLEUint(0x10); } else { WriteLEUint(0); } if (entry.Offset >= 0xffffffffL) { WriteLEUint(uint.MaxValue); } else { WriteLEUint((uint)((int)entry.Offset)); } if (buffer.Length > 0) { baseStream_.Write(buffer, 0, buffer.Length); } if (entryData.Length > 0) { baseStream_.Write(entryData, 0, entryData.Length); } byte[] buffer3 = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0]; if (buffer3.Length > 0) { baseStream_.Write(buffer3, 0, buffer3.Length); } return (((0x2e + buffer.Length) + entryData.Length) + buffer3.Length); }
public override void Finish() { if (entries != null) { if (curEntry != null) { CloseEntry(); } long count = entries.Count; long sizeEntries = 0L; foreach (ZipEntry entry in entries) { WriteLeInt(0x2014b50); WriteLeShort(0x33); WriteLeShort(entry.Version); WriteLeShort(entry.Flags); WriteLeShort((short)entry.CompressionMethodForHeader); WriteLeInt((int)entry.DosTime); WriteLeInt((int)entry.Crc); if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL)) { WriteLeInt(-1); } else { WriteLeInt((int)entry.CompressedSize); } if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL)) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Size); } byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name); if (buffer.Length > 0xffff) { throw new ZipException("Name too long."); } ZipExtraData extraData = new ZipExtraData(entry.ExtraData); if (entry.CentralHeaderRequiresZip64) { extraData.StartNewEntry(); if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL)) { extraData.AddLeLong(entry.Size); } if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL)) { extraData.AddLeLong(entry.CompressedSize); } if (entry.Offset >= 0xffffffffL) { extraData.AddLeLong(entry.Offset); } extraData.AddNewEntry(1); } else { extraData.Delete(1); } if (entry.AESKeySize > 0) { AddExtraDataAES(entry, extraData); } byte[] entryData = extraData.GetEntryData(); byte[] buffer3 = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0]; if (buffer3.Length > 0xffff) { throw new ZipException("Comment too long."); } WriteLeShort(buffer.Length); WriteLeShort(entryData.Length); WriteLeShort(buffer3.Length); WriteLeShort(0); WriteLeShort(0); if (entry.ExternalFileAttributes != -1) { WriteLeInt(entry.ExternalFileAttributes); } else if (entry.IsDirectory) { WriteLeInt(0x10); } else { WriteLeInt(0); } if (entry.Offset >= 0xffffffffL) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Offset); } if (buffer.Length > 0) { baseOutputStream_.Write(buffer, 0, buffer.Length); } if (entryData.Length > 0) { baseOutputStream_.Write(entryData, 0, entryData.Length); } if (buffer3.Length > 0) { baseOutputStream_.Write(buffer3, 0, buffer3.Length); } sizeEntries += ((0x2e + buffer.Length) + entryData.Length) + buffer3.Length; } using (ZipHelperStream stream = new ZipHelperStream(baseOutputStream_)) { stream.WriteEndOfCentralDirectory(count, sizeEntries, offset, zipComment); } entries = null; } }