/// <summary> /// Finishes the stream. This will write the central directory at the /// end of the zip file and flush the stream. /// </summary> /// <remarks> /// This is automatically called when the stream is closed. /// </remarks> /// <exception cref="System.IO.IOException"> /// An I/O error occurs. /// </exception> /// <exception cref="ZipException"> /// Comment exceeds the maximum length<br/> /// Entry name exceeds the maximum length /// </exception> public override void Finish() { if (entries == null) { return; } if (curEntry != null) { CloseEntry(); } long numEntries = entries.Count; long sizeEntries = 0; foreach (ZipEntry entry in entries) { WriteLeInt(ZipConstants.CentralHeaderSignature); WriteLeShort(ZipConstants.VersionMadeBy); WriteLeShort(entry.Version); WriteLeShort(entry.Flags); WriteLeShort((short)entry.CompressionMethodForHeader); WriteLeInt((int)entry.DosTime); WriteLeInt((int)entry.Crc); if ( entry.IsZip64Forced() || (entry.CompressedSize >= uint.MaxValue) ) { WriteLeInt(-1); } else { WriteLeInt((int)entry.CompressedSize); } if ( entry.IsZip64Forced() || (entry.Size >= uint.MaxValue) ) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Size); } byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); if (name.Length > 0xffff) { throw new ZipException("Name too long."); } ZipExtraData ed = new ZipExtraData(entry.ExtraData); if ( entry.CentralHeaderRequiresZip64 ) { ed.StartNewEntry(); if ( entry.IsZip64Forced() || (entry.Size >= 0xffffffff) ) { ed.AddLeLong(entry.Size); } if ( entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffff) ) { ed.AddLeLong(entry.CompressedSize); } if ( entry.Offset >= 0xffffffff ) { ed.AddLeLong(entry.Offset); } ed.AddNewEntry(1); } else { ed.Delete(1); } #if !NET_1_1 && !NETCF_2_0 if (entry.AESKeySize > 0) { AddExtraDataAES(entry, ed); } #endif byte[] extra = ed.GetEntryData(); byte[] entryComment = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0]; if (entryComment.Length > 0xffff) { throw new ZipException("Comment too long."); } WriteLeShort(name.Length); WriteLeShort(extra.Length); WriteLeShort(entryComment.Length); WriteLeShort(0); // disk number WriteLeShort(0); // internal file attributes // external file attributes if (entry.ExternalFileAttributes != -1) { WriteLeInt(entry.ExternalFileAttributes); } else { if (entry.IsDirectory) { // mark entry as directory (from nikolam.AT.perfectinfo.com) WriteLeInt(16); } else { WriteLeInt(0); } } if ( entry.Offset >= uint.MaxValue ) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Offset); } if ( name.Length > 0 ) { baseOutputStream_.Write(name, 0, name.Length); } if ( extra.Length > 0 ) { baseOutputStream_.Write(extra, 0, extra.Length); } if ( entryComment.Length > 0 ) { baseOutputStream_.Write(entryComment, 0, entryComment.Length); } sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; } using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) { zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment); } entries = null; }
// 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); if (name.Length > 0xFFFF) { throw new ZipException("Entry name too long."); } 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 ( !ed.Find(1) ) { throw new ZipException("Internal error cant find extra data"); } 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); } }
public void BasicOperations() { var zed = new ZipExtraData(null); Assert.AreEqual(0, zed.Length); zed = new ZipExtraData(new byte[] { 1, 0, 0, 0 }); Assert.AreEqual(4, zed.Length, "A length should be 4"); var zed2 = new ZipExtraData(); Assert.AreEqual(0, zed2.Length); zed2.AddEntry(1, new byte[] { }); byte[] data = zed.GetEntryData(); for (int i = 0; i < data.Length; ++i) { Assert.AreEqual(zed2.GetEntryData()[i], data[i]); } Assert.AreEqual(4, zed2.Length, "A1 length should be 4"); bool findResult = zed.Find(2); Assert.IsFalse(findResult, "A - Shouldnt find tag 2"); findResult = zed.Find(1); Assert.IsTrue(findResult, "A - Should find tag 1"); Assert.AreEqual(0, zed.ValueLength, "A- Length of entry should be 0"); Assert.AreEqual(-1, zed.ReadByte()); Assert.AreEqual(0, zed.GetStreamForTag(1).Length, "A - Length of stream should be 0"); zed = new ZipExtraData(new byte[] { 1, 0, 3, 0, 1, 2, 3 }); Assert.AreEqual(7, zed.Length, "Expected a length of 7"); findResult = zed.Find(1); Assert.IsTrue(findResult, "B - Should find tag 1"); Assert.AreEqual(3, zed.ValueLength, "B - Length of entry should be 3"); for (int i = 1; i <= 3; ++i) { Assert.AreEqual(i, zed.ReadByte()); } Assert.AreEqual(-1, zed.ReadByte()); Stream s = zed.GetStreamForTag(1); Assert.AreEqual(3, s.Length, "B.1 Stream length should be 3"); for (int i = 1; i <= 3; ++i) { Assert.AreEqual(i, s.ReadByte()); } Assert.AreEqual(-1, s.ReadByte()); zed = new ZipExtraData(new byte[] { 1, 0, 3, 0, 1, 2, 3, 2, 0, 1, 0, 56 }); Assert.AreEqual(12, zed.Length, "Expected a length of 12"); findResult = zed.Find(1); Assert.IsTrue(findResult, "C.1 - Should find tag 1"); Assert.AreEqual(3, zed.ValueLength, "C.1 - Length of entry should be 3"); for (int i = 1; i <= 3; ++i) { Assert.AreEqual(i, zed.ReadByte()); } Assert.AreEqual(-1, zed.ReadByte()); findResult = zed.Find(2); Assert.IsTrue(findResult, "C.2 - Should find tag 2"); Assert.AreEqual(1, zed.ValueLength, "C.2 - Length of entry should be 1"); Assert.AreEqual(56, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); s = zed.GetStreamForTag(2); Assert.AreEqual(1, s.Length); Assert.AreEqual(56, s.ReadByte()); Assert.AreEqual(-1, s.ReadByte()); zed = new ZipExtraData(); zed.AddEntry(7, new byte[] { 33, 44, 55 }); findResult = zed.Find(7); Assert.IsTrue(findResult, "Add.1 should find new tag"); Assert.AreEqual(3, zed.ValueLength, "Add.1 length should be 3"); Assert.AreEqual(33, zed.ReadByte()); Assert.AreEqual(44, zed.ReadByte()); Assert.AreEqual(55, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); zed.AddEntry(7, null); findResult = zed.Find(7); Assert.IsTrue(findResult, "Add.2 should find new tag"); Assert.AreEqual(0, zed.ValueLength, "Add.2 length should be 0"); zed.StartNewEntry(); zed.AddData(0xae); zed.AddNewEntry(55); findResult = zed.Find(55); Assert.IsTrue(findResult, "Add.3 should find new tag"); Assert.AreEqual(1, zed.ValueLength, "Add.3 length should be 1"); Assert.AreEqual(0xae, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); zed = new ZipExtraData(); zed.StartNewEntry(); zed.AddLeLong(0); zed.AddLeLong(-4); zed.AddLeLong(-1); zed.AddLeLong(long.MaxValue); zed.AddLeLong(long.MinValue); zed.AddLeLong(0x123456789ABCDEF0); zed.AddLeLong(unchecked ((long)0xFEDCBA9876543210)); zed.AddNewEntry(567); s = zed.GetStreamForTag(567); long longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(0, longValue, "Expected long value of zero"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(-4, longValue, "Expected long value of -4"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(-1, longValue, "Expected long value of -1"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(long.MaxValue, longValue, "Expected long value of MaxValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(long.MinValue, longValue, "Expected long value of MinValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(0x123456789abcdef0, longValue, "Expected long value of MinValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(unchecked ((long)0xFEDCBA9876543210), longValue, "Expected long value of MinValue"); }
/// <summary> /// Starts a new Zip entry. It automatically closes the previous /// entry if present. /// All entry elements bar name are optional, but must be correct if present. /// If the compression method is stored and the output is not patchable /// the compression for that entry is automatically changed to deflate level 0 /// </summary> /// <param name="entry"> /// the entry. /// </param> /// <exception cref="System.ArgumentNullException"> /// if entry passed is null. /// </exception> /// <exception cref="System.IO.IOException"> /// if an I/O error occured. /// </exception> /// <exception cref="System.InvalidOperationException"> /// if stream was finished /// </exception> /// <exception cref="ZipException"> /// Too many entries in the Zip file<br/> /// Entry name is too long<br/> /// Finish has already been called<br/> /// </exception> public void PutNextEntry(ZipEntry entry) { if ( entry == null ) { throw new ArgumentNullException("entry"); } if (entries == null) { throw new InvalidOperationException("ZipOutputStream was finished"); } if (curEntry != null) { CloseEntry(); } if (entries.Count == int.MaxValue) { throw new ZipException("Too many entries for Zip file"); } CompressionMethod method = entry.CompressionMethod; int compressionLevel = defaultCompressionLevel; // Clear flags that the library manages internally entry.Flags &= (int)GeneralBitFlags.UnicodeText; patchEntryHeader = false; bool headerInfoAvailable; // No need to compress - definitely no data. if (entry.Size == 0) { entry.CompressedSize = entry.Size; entry.Crc = 0; method = CompressionMethod.Stored; headerInfoAvailable = true; } else { headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc; // Switch to deflation if storing isnt possible. if (method == CompressionMethod.Stored) { if (!headerInfoAvailable) { if (!CanPatchEntries) { // Can't patch entries so storing is not possible. method = CompressionMethod.Deflated; compressionLevel = 0; } } else // entry.size must be > 0 { entry.CompressedSize = entry.Size; headerInfoAvailable = entry.HasCrc; } } } if (headerInfoAvailable == false) { if (CanPatchEntries == false) { // Only way to record size and compressed size is to append a data descriptor // after compressed data. // Stored entries of this form have already been converted to deflating. entry.Flags |= 8; } else { patchEntryHeader = true; } } if (Password != null) { entry.IsCrypted = true; if (entry.Crc < 0) { // Need to append a data descriptor as the crc isnt available for use // with encryption, the date is used instead. Setting the flag // indicates this to the decompressor. entry.Flags |= 8; } } entry.Offset = offset; entry.CompressionMethod = (CompressionMethod)method; curMethod = method; sizePatchPos = -1; if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) { entry.ForceZip64(); } // Write the local file header WriteLeInt(ZipConstants.LocalHeaderSignature); WriteLeShort(entry.Version); WriteLeShort(entry.Flags); WriteLeShort((byte)entry.CompressionMethodForHeader); WriteLeInt((int)entry.DosTime); // TODO: Refactor header writing. Its done in several places. 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 (patchEntryHeader) { crcPatchPos = baseOutputStream_.Position; } WriteLeInt(0); // Crc if ( patchEntryHeader ) { sizePatchPos = baseOutputStream_.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); if (name.Length > 0xFFFF) { throw new ZipException("Entry name too long."); } ZipExtraData ed = new ZipExtraData(entry.ExtraData); if (entry.LocalHeaderRequiresZip64) { ed.StartNewEntry(); if (headerInfoAvailable) { ed.AddLeLong(entry.Size); ed.AddLeLong(entry.CompressedSize); } else { ed.AddLeLong(-1); ed.AddLeLong(-1); } ed.AddNewEntry(1); if ( !ed.Find(1) ) { throw new ZipException("Internal error cant find extra data"); } if ( patchEntryHeader ) { sizePatchPos = ed.CurrentReadIndex; } } else { ed.Delete(1); } #if !NET_1_1 && !NETCF_2_0 if (entry.AESKeySize > 0) { AddExtraDataAES(entry, ed); } #endif byte[] extra = ed.GetEntryData(); WriteLeShort(name.Length); WriteLeShort(extra.Length); if ( name.Length > 0 ) { baseOutputStream_.Write(name, 0, name.Length); } if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { sizePatchPos += baseOutputStream_.Position; } if ( extra.Length > 0 ) { baseOutputStream_.Write(extra, 0, extra.Length); } offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length; // Fix offsetOfCentraldir for AES if (entry.AESKeySize > 0) offset += entry.AESOverheadSize; // Activate the entry. curEntry = entry; crc.Reset(); if (method == CompressionMethod.Deflated) { deflater_.Reset(); deflater_.SetLevel(compressionLevel); } size = 0; if (entry.IsCrypted) { #if !NET_1_1 && !NETCF_2_0 if (entry.AESKeySize > 0) { WriteAESHeader(entry); } else #endif { if (entry.Crc < 0) { // so testing Zip will says its ok WriteEncryptionHeader(entry.DosTime << 16); } else { WriteEncryptionHeader(entry.Crc); } } } }
int WriteCentralDirectoryHeader(ZipEntry entry) { if ( entry.CompressedSize < 0 ) { throw new ZipException("Attempt to write central directory entry with unknown csize"); } if ( entry.Size < 0 ) { throw new ZipException("Attempt to write central directory entry with unknown size"); } if ( entry.Crc < 0 ) { throw new ZipException("Attempt to write central directory entry with unknown crc"); } // 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); if ( name.Length > 0xFFFF ) { throw new ZipException("Entry name is too long."); } 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; }
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); if ( name.Length > 0xFFFF ) { throw new ZipException("Entry name too long."); } 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 ) { if ( !ed.Find(1) ) { throw new ZipException("Internal error cannot find extra data"); } update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex; } if ( entry.ExtraData.Length > 0 ) { baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length); } }
public void Deleting() { var zed = new ZipExtraData(); Assert.AreEqual(0, zed.Length); // Tag 1 Totoal length 10 zed.AddEntry(1, new byte[]{10, 11, 12, 13, 14, 15}); Assert.AreEqual(10, zed.Length, "Length should be 10"); Assert.AreEqual(10, zed.GetEntryData().Length, "Data length should be 10"); // Tag 2 total length 9 zed.AddEntry(2, new byte[]{20, 21, 22, 23, 24}); Assert.AreEqual(19, zed.Length, "Length should be 19"); Assert.AreEqual(19, zed.GetEntryData().Length, "Data length should be 19"); // Tag 3 Total Length 6 zed.AddEntry(3, new byte[]{30, 31}); Assert.AreEqual(25, zed.Length, "Length should be 25"); Assert.AreEqual(25, zed.GetEntryData().Length, "Data length should be 25"); zed.Delete(2); Assert.AreEqual(16, zed.Length, "Length should be 16"); Assert.AreEqual(16, zed.GetEntryData().Length, "Data length should be 16"); // Tag 2 total length 9 zed.AddEntry(2, new byte[]{20, 21, 22, 23, 24}); Assert.AreEqual(25, zed.Length, "Length should be 25"); Assert.AreEqual(25, zed.GetEntryData().Length, "Data length should be 25"); zed.AddEntry(3, null); Assert.AreEqual(23, zed.Length, "Length should be 23"); Assert.AreEqual(23, zed.GetEntryData().Length, "Data length should be 23"); }
public void BasicOperations() { var zed = new ZipExtraData(null); Assert.AreEqual(0, zed.Length); zed = new ZipExtraData(new byte[]{1, 0, 0, 0}); Assert.AreEqual(4, zed.Length, "A length should be 4"); var zed2 = new ZipExtraData(); Assert.AreEqual(0, zed2.Length); zed2.AddEntry(1, new byte[]{}); var data = zed.GetEntryData(); for (var i = 0; i < data.Length; ++i) { Assert.AreEqual(zed2.GetEntryData()[i], data[i]); } Assert.AreEqual(4, zed2.Length, "A1 length should be 4"); var findResult = zed.Find(2); Assert.IsFalse(findResult, "A - Shouldnt find tag 2"); findResult = zed.Find(1); Assert.IsTrue(findResult, "A - Should find tag 1"); Assert.AreEqual(0, zed.ValueLength, "A- Length of entry should be 0"); Assert.AreEqual(-1, zed.ReadByte()); Assert.AreEqual(0, zed.GetStreamForTag(1).Length, "A - Length of stream should be 0"); zed = new ZipExtraData(new byte[]{1, 0, 3, 0, 1, 2, 3}); Assert.AreEqual(7, zed.Length, "Expected a length of 7"); findResult = zed.Find(1); Assert.IsTrue(findResult, "B - Should find tag 1"); Assert.AreEqual(3, zed.ValueLength, "B - Length of entry should be 3"); for (var i = 1; i <= 3; ++i) { Assert.AreEqual(i, zed.ReadByte()); } Assert.AreEqual(-1, zed.ReadByte()); var s = zed.GetStreamForTag(1); Assert.AreEqual(3, s.Length, "B.1 Stream length should be 3"); for (var i = 1; i <= 3; ++i) { Assert.AreEqual(i, s.ReadByte()); } Assert.AreEqual(-1, s.ReadByte()); zed = new ZipExtraData(new byte[]{1, 0, 3, 0, 1, 2, 3, 2, 0, 1, 0, 56}); Assert.AreEqual(12, zed.Length, "Expected a length of 12"); findResult = zed.Find(1); Assert.IsTrue(findResult, "C.1 - Should find tag 1"); Assert.AreEqual(3, zed.ValueLength, "C.1 - Length of entry should be 3"); for (var i = 1; i <= 3; ++i) { Assert.AreEqual(i, zed.ReadByte()); } Assert.AreEqual(-1, zed.ReadByte()); findResult = zed.Find(2); Assert.IsTrue(findResult, "C.2 - Should find tag 2"); Assert.AreEqual(1, zed.ValueLength, "C.2 - Length of entry should be 1"); Assert.AreEqual(56, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); s = zed.GetStreamForTag(2); Assert.AreEqual(1, s.Length); Assert.AreEqual(56, s.ReadByte()); Assert.AreEqual(-1, s.ReadByte()); zed = new ZipExtraData(); zed.AddEntry(7, new byte[]{33, 44, 55}); findResult = zed.Find(7); Assert.IsTrue(findResult, "Add.1 should find new tag"); Assert.AreEqual(3, zed.ValueLength, "Add.1 length should be 3"); Assert.AreEqual(33, zed.ReadByte()); Assert.AreEqual(44, zed.ReadByte()); Assert.AreEqual(55, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); zed.AddEntry(7, null); findResult = zed.Find(7); Assert.IsTrue(findResult, "Add.2 should find new tag"); Assert.AreEqual(0, zed.ValueLength, "Add.2 length should be 0"); zed.StartNewEntry(); zed.AddData(0xae); zed.AddNewEntry(55); findResult = zed.Find(55); Assert.IsTrue(findResult, "Add.3 should find new tag"); Assert.AreEqual(1, zed.ValueLength, "Add.3 length should be 1"); Assert.AreEqual(0xae, zed.ReadByte()); Assert.AreEqual(-1, zed.ReadByte()); zed = new ZipExtraData(); zed.StartNewEntry(); zed.AddLeLong(0); zed.AddLeLong(-4); zed.AddLeLong(-1); zed.AddLeLong(long.MaxValue); zed.AddLeLong(long.MinValue); zed.AddLeLong(0x123456789ABCDEF0); zed.AddLeLong(unchecked((long) 0xFEDCBA9876543210)); zed.AddNewEntry(567); s = zed.GetStreamForTag(567); var longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(0, longValue, "Expected long value of zero"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(-4, longValue, "Expected long value of -4"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(-1, longValue, "Expected long value of -1"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(long.MaxValue, longValue, "Expected long value of MaxValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(long.MinValue, longValue, "Expected long value of MinValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(0x123456789abcdef0, longValue, "Expected long value of MinValue"); longValue = ReadLong(s); Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch"); Assert.AreEqual(unchecked((long) 0xFEDCBA9876543210), longValue, "Expected long value of MinValue"); }
public void PasswordCheckingWithDateInExtraData() { var ms = new MemoryStream(); var checkTime = new DateTime(2010, 10, 16, 0, 3, 28); using (var zos = new ZipOutputStream(ms)) { zos.IsStreamOwner = false; zos.Password = "******"; var ze = new ZipEntry("uno"); ze.DateTime = new DateTime(1998, 6, 5, 4, 3, 2); var zed = new ZipExtraData(); zed.StartNewEntry(); zed.AddData(1); var delta = checkTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); var seconds = (int) delta.TotalSeconds; zed.AddLeInt(seconds); zed.AddNewEntry(0x5455); ze.ExtraData = zed.GetEntryData(); zos.PutNextEntry(ze); zos.WriteByte(54); } ms.Position = 0; using (var zis = new ZipInputStream(ms)) { zis.Password = "******"; var uno = zis.GetNextEntry(); var theByte = (byte) zis.ReadByte(); Assert.AreEqual(54, theByte); Assert.AreEqual(-1, zis.ReadByte()); Assert.AreEqual(checkTime, uno.DateTime); } }