From e296ead7fd284e18a296b8ec2c56f81f8e3fa7d3 Mon Sep 17 00:00:00 2001 From: ABykiev Date: Thu, 3 Aug 2023 22:17:11 +0300 Subject: [PATCH 1/3] Fix ZipFile constructor breaking change This PR fixes #839 --- src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs index 69bb9f6a9..47552f227 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs @@ -387,6 +387,19 @@ private bool HaveKeys #region Constructors + /// + /// Opens a Zip file with the given name for reading. + /// + /// The name of the file to open. + /// The argument supplied is null. + /// + /// An i/o error occurs + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(string name): this(name, null) { } + /// /// Opens a Zip file with the given name for reading. /// @@ -399,7 +412,7 @@ private bool HaveKeys /// /// The file doesn't contain a valid zip archive. /// - public ZipFile(string name, StringCodec stringCodec = null) + public ZipFile(string name, StringCodec stringCodec) { name_ = name ?? throw new ArgumentNullException(nameof(name)); From ab88dd37858aaf5d38cba875a63fca212b913ba7 Mon Sep 17 00:00:00 2001 From: ABykiev Date: Thu, 3 Aug 2023 22:40:21 +0300 Subject: [PATCH 2/3] Fix another constructor too --- src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs | 86 ++++++++++++++-------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs index 47552f227..d24e5955f 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs @@ -398,7 +398,11 @@ private bool HaveKeys /// /// The file doesn't contain a valid zip archive. /// - public ZipFile(string name): this(name, null) { } + public ZipFile(string name) : + this(name, null) + { + + } /// /// Opens a Zip file with the given name for reading. @@ -513,6 +517,29 @@ public ZipFile(Stream stream) : } + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// true to leave the stream open when the ZipFile is disposed, false to dispose of it + /// + /// An i/o error occurs + /// + /// + /// The stream doesn't contain a valid zip archive.
+ ///
+ /// + /// The stream doesnt support seeking. + /// + /// + /// The stream argument is null. + /// + public ZipFile(Stream stream, bool leaveOpen) : + this(stream, leaveOpen, null) + { + + } + /// /// Opens a Zip file reading the given . /// @@ -531,7 +558,7 @@ public ZipFile(Stream stream) : /// /// The stream argument is null. /// - public ZipFile(Stream stream, bool leaveOpen, StringCodec stringCodec = null) + public ZipFile(Stream stream, bool leaveOpen, StringCodec stringCodec) { if (stream == null) { @@ -762,7 +789,8 @@ public Encoding ZipCryptoEncoding /// public StringCodec StringCodec { - set { + set + { _stringCodec = value; if (!isNewArchive_) { @@ -1131,7 +1159,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) bool testData = (tests & HeaderTest.Extract) != 0; var entryAbsOffset = offsetOfFirstEntry + entry.Offset; - + baseStream_.Seek(entryAbsOffset, SeekOrigin.Begin); var signature = (int)ReadLEUint(); @@ -1207,9 +1235,9 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) throw new ZipException($"Version required to extract this entry not supported ({extractVersion})"); } - const GeneralBitFlags notSupportedFlags = GeneralBitFlags.Patched - | GeneralBitFlags.StrongEncryption - | GeneralBitFlags.EnhancedCompress + const GeneralBitFlags notSupportedFlags = GeneralBitFlags.Patched + | GeneralBitFlags.StrongEncryption + | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked; if (localFlags.HasAny(notSupportedFlags)) { @@ -1626,8 +1654,8 @@ public void CommitUpdate() { // Create an empty archive if none existed originally. if (entries_.Length != 0) return; - byte[] theComment = (newComment_ != null) - ? newComment_.RawComment + byte[] theComment = (newComment_ != null) + ? newComment_.RawComment : _stringCodec.ZipArchiveCommentEncoding.GetBytes(comment_); ZipFormat.WriteEndOfCentralDirectory(baseStream_, 0, 0, 0, theComment); } @@ -2532,15 +2560,15 @@ private void CopyBytes(ZipUpdate update, Stream destination, Stream source, /// The descriptor size, zero if there isn't one. private static int GetDescriptorSize(ZipUpdate update, bool includingSignature) { - if (!((GeneralBitFlags)update.Entry.Flags).HasAny(GeneralBitFlags.Descriptor)) + if (!((GeneralBitFlags)update.Entry.Flags).HasAny(GeneralBitFlags.Descriptor)) return 0; - - var descriptorWithSignature = update.Entry.LocalHeaderRequiresZip64 - ? ZipConstants.Zip64DataDescriptorSize + + var descriptorWithSignature = update.Entry.LocalHeaderRequiresZip64 + ? ZipConstants.Zip64DataDescriptorSize : ZipConstants.DataDescriptorSize; - return includingSignature - ? descriptorWithSignature + return includingSignature + ? descriptorWithSignature : descriptorWithSignature - sizeof(int); } @@ -2827,7 +2855,7 @@ private void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destin // Clumsy way of handling retrieving the original name and extra data length for now. // TODO: Stop re-reading name and data length in CopyEntryDirect. - + uint nameLength = ReadLEUshort(); uint extraLength = ReadLEUshort(); @@ -2962,7 +2990,7 @@ private void UpdateCommentOnly() } finally { - if(updateFile != baseStream_) + if (updateFile != baseStream_) updateFile.Dispose(); } @@ -3127,7 +3155,7 @@ private void RunUpdates() } byte[] theComment = newComment_?.RawComment ?? _stringCodec.ZipArchiveCommentEncoding.GetBytes(comment_); - ZipFormat.WriteEndOfCentralDirectory(workFile.baseStream_, updateCount_, + ZipFormat.WriteEndOfCentralDirectory(workFile.baseStream_, updateCount_, sizeEntries, centralDirOffset, theComment); endOfStream = workFile.baseStream_.Position; @@ -3469,7 +3497,7 @@ private ulong ReadLEUlong() #endregion Reading // NOTE this returns the offset of the first byte after the signature. - private long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + private long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) => ZipFormat.LocateBlockWithSignature(baseStream_, signature, endLocation, minimumBlockSize, maximumVariableData); /// @@ -3527,14 +3555,14 @@ private void ReadEntries() } bool isZip64 = false; - + // Check if zip64 header information is required. bool requireZip64 = thisDiskNumber == 0xffff || - startCentralDirDisk == 0xffff || - entriesForThisDisk == 0xffff || - entriesForWholeCentralDir == 0xffff || - centralDirSize == 0xffffffff || - offsetOfCentralDir == 0xffffffff; + startCentralDirDisk == 0xffff || + entriesForThisDisk == 0xffff || + entriesForWholeCentralDir == 0xffff || + centralDirSize == 0xffffffff || + offsetOfCentralDir == 0xffffffff; // #357 - always check for the existence of the Zip64 central directory. // #403 - Take account of the fixed size of the locator when searching. @@ -3625,7 +3653,7 @@ private void ReadEntries() int extraLen = ReadLEUshort(); int commentLen = ReadLEUshort(); - + // ReSharper disable once UnusedVariable, Currently unused but needs to be read to offset the stream int diskStartNo = ReadLEUshort(); // ReSharper disable once UnusedVariable, Currently unused but needs to be read to offset the stream @@ -3722,9 +3750,9 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) int saltLen = entry.AESSaltLen; byte[] saltBytes = new byte[saltLen]; int saltIn = StreamUtils.ReadRequestedBytes(baseStream, saltBytes, offset: 0, saltLen); - + if (saltIn != saltLen) throw new ZipException($"AES Salt expected {saltLen} git {saltIn}"); - + byte[] pwdVerifyRead = new byte[2]; StreamUtils.ReadFully(baseStream, pwdVerifyRead); int blockSize = entry.AESKeySize / 8; // bits to bytes @@ -3768,7 +3796,7 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) private Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) { if (entry.Version >= ZipConstants.VersionStrongEncryption && - entry.HasFlag(GeneralBitFlags.StrongEncryption)) return null; + entry.HasFlag(GeneralBitFlags.StrongEncryption)) return null; var classicManaged = new PkzipClassicManaged(); From 537537a206fd5ac43fcf74866cdf003d3653a41c Mon Sep 17 00:00:00 2001 From: ABykiev Date: Thu, 3 Aug 2023 22:41:40 +0300 Subject: [PATCH 3/3] Do not change formatting --- src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs | 69 +++++++++++----------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs index d24e5955f..951cc6e20 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs @@ -398,9 +398,9 @@ private bool HaveKeys /// /// The file doesn't contain a valid zip archive. /// - public ZipFile(string name) : - this(name, null) - { + public ZipFile(string name) : + this(name, null) + { } @@ -534,10 +534,10 @@ public ZipFile(Stream stream) : /// /// The stream argument is null. /// - public ZipFile(Stream stream, bool leaveOpen) : - this(stream, leaveOpen, null) - { - + public ZipFile(Stream stream, bool leaveOpen) : + this(stream, leaveOpen, null) + { + } /// @@ -789,8 +789,7 @@ public Encoding ZipCryptoEncoding /// public StringCodec StringCodec { - set - { + set { _stringCodec = value; if (!isNewArchive_) { @@ -1159,7 +1158,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) bool testData = (tests & HeaderTest.Extract) != 0; var entryAbsOffset = offsetOfFirstEntry + entry.Offset; - + baseStream_.Seek(entryAbsOffset, SeekOrigin.Begin); var signature = (int)ReadLEUint(); @@ -1235,9 +1234,9 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) throw new ZipException($"Version required to extract this entry not supported ({extractVersion})"); } - const GeneralBitFlags notSupportedFlags = GeneralBitFlags.Patched - | GeneralBitFlags.StrongEncryption - | GeneralBitFlags.EnhancedCompress + const GeneralBitFlags notSupportedFlags = GeneralBitFlags.Patched + | GeneralBitFlags.StrongEncryption + | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked; if (localFlags.HasAny(notSupportedFlags)) { @@ -1654,8 +1653,8 @@ public void CommitUpdate() { // Create an empty archive if none existed originally. if (entries_.Length != 0) return; - byte[] theComment = (newComment_ != null) - ? newComment_.RawComment + byte[] theComment = (newComment_ != null) + ? newComment_.RawComment : _stringCodec.ZipArchiveCommentEncoding.GetBytes(comment_); ZipFormat.WriteEndOfCentralDirectory(baseStream_, 0, 0, 0, theComment); } @@ -2560,15 +2559,15 @@ private void CopyBytes(ZipUpdate update, Stream destination, Stream source, /// The descriptor size, zero if there isn't one. private static int GetDescriptorSize(ZipUpdate update, bool includingSignature) { - if (!((GeneralBitFlags)update.Entry.Flags).HasAny(GeneralBitFlags.Descriptor)) + if (!((GeneralBitFlags)update.Entry.Flags).HasAny(GeneralBitFlags.Descriptor)) return 0; - - var descriptorWithSignature = update.Entry.LocalHeaderRequiresZip64 - ? ZipConstants.Zip64DataDescriptorSize + + var descriptorWithSignature = update.Entry.LocalHeaderRequiresZip64 + ? ZipConstants.Zip64DataDescriptorSize : ZipConstants.DataDescriptorSize; - return includingSignature - ? descriptorWithSignature + return includingSignature + ? descriptorWithSignature : descriptorWithSignature - sizeof(int); } @@ -2855,7 +2854,7 @@ private void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destin // Clumsy way of handling retrieving the original name and extra data length for now. // TODO: Stop re-reading name and data length in CopyEntryDirect. - + uint nameLength = ReadLEUshort(); uint extraLength = ReadLEUshort(); @@ -2990,7 +2989,7 @@ private void UpdateCommentOnly() } finally { - if (updateFile != baseStream_) + if(updateFile != baseStream_) updateFile.Dispose(); } @@ -3155,7 +3154,7 @@ private void RunUpdates() } byte[] theComment = newComment_?.RawComment ?? _stringCodec.ZipArchiveCommentEncoding.GetBytes(comment_); - ZipFormat.WriteEndOfCentralDirectory(workFile.baseStream_, updateCount_, + ZipFormat.WriteEndOfCentralDirectory(workFile.baseStream_, updateCount_, sizeEntries, centralDirOffset, theComment); endOfStream = workFile.baseStream_.Position; @@ -3497,7 +3496,7 @@ private ulong ReadLEUlong() #endregion Reading // NOTE this returns the offset of the first byte after the signature. - private long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + private long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) => ZipFormat.LocateBlockWithSignature(baseStream_, signature, endLocation, minimumBlockSize, maximumVariableData); /// @@ -3555,14 +3554,14 @@ private void ReadEntries() } bool isZip64 = false; - + // Check if zip64 header information is required. bool requireZip64 = thisDiskNumber == 0xffff || - startCentralDirDisk == 0xffff || - entriesForThisDisk == 0xffff || - entriesForWholeCentralDir == 0xffff || - centralDirSize == 0xffffffff || - offsetOfCentralDir == 0xffffffff; + startCentralDirDisk == 0xffff || + entriesForThisDisk == 0xffff || + entriesForWholeCentralDir == 0xffff || + centralDirSize == 0xffffffff || + offsetOfCentralDir == 0xffffffff; // #357 - always check for the existence of the Zip64 central directory. // #403 - Take account of the fixed size of the locator when searching. @@ -3653,7 +3652,7 @@ private void ReadEntries() int extraLen = ReadLEUshort(); int commentLen = ReadLEUshort(); - + // ReSharper disable once UnusedVariable, Currently unused but needs to be read to offset the stream int diskStartNo = ReadLEUshort(); // ReSharper disable once UnusedVariable, Currently unused but needs to be read to offset the stream @@ -3750,9 +3749,9 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) int saltLen = entry.AESSaltLen; byte[] saltBytes = new byte[saltLen]; int saltIn = StreamUtils.ReadRequestedBytes(baseStream, saltBytes, offset: 0, saltLen); - + if (saltIn != saltLen) throw new ZipException($"AES Salt expected {saltLen} git {saltIn}"); - + byte[] pwdVerifyRead = new byte[2]; StreamUtils.ReadFully(baseStream, pwdVerifyRead); int blockSize = entry.AESKeySize / 8; // bits to bytes @@ -3796,7 +3795,7 @@ private Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) private Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) { if (entry.Version >= ZipConstants.VersionStrongEncryption && - entry.HasFlag(GeneralBitFlags.StrongEncryption)) return null; + entry.HasFlag(GeneralBitFlags.StrongEncryption)) return null; var classicManaged = new PkzipClassicManaged();