diff --git a/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs b/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs index 2b5f1cccb..a072d193e 100644 --- a/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs +++ b/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs @@ -46,8 +46,8 @@ namespace ICSharpCode.SharpZipLib.Checksum /// checked separately. (Any sequence of zeroes has a Fletcher /// checksum of zero.)" /// - /// - /// + /// + /// public sealed class Adler32 : IChecksum { #region Instance Fields diff --git a/src/ICSharpCode.SharpZipLib/Core/NameFilter.cs b/src/ICSharpCode.SharpZipLib/Core/NameFilter.cs index 3909104c6..31712c58a 100644 --- a/src/ICSharpCode.SharpZipLib/Core/NameFilter.cs +++ b/src/ICSharpCode.SharpZipLib/Core/NameFilter.cs @@ -41,7 +41,7 @@ public NameFilter(string filter) /// Test a string to see if it is a valid regular expression. /// /// The expression to test. - /// True if expression is a valid false otherwise. + /// True if expression is a valid false otherwise. public static bool IsValidExpression(string expression) { bool result = true; diff --git a/src/ICSharpCode.SharpZipLib/Core/PathFilter.cs b/src/ICSharpCode.SharpZipLib/Core/PathFilter.cs index 1e52964f7..821b01256 100644 --- a/src/ICSharpCode.SharpZipLib/Core/PathFilter.cs +++ b/src/ICSharpCode.SharpZipLib/Core/PathFilter.cs @@ -118,7 +118,7 @@ public class ExtendedPathFilter : PathFilter /// /// The filename to test. /// True if the filter matches, false otherwise. - /// The doesnt exist + /// The doesnt exist public override bool IsMatch(string name) { bool result = base.IsMatch(name); diff --git a/src/ICSharpCode.SharpZipLib/Core/PathUtils.cs b/src/ICSharpCode.SharpZipLib/Core/PathUtils.cs index 57875cdbe..1d01a4f02 100644 --- a/src/ICSharpCode.SharpZipLib/Core/PathUtils.cs +++ b/src/ICSharpCode.SharpZipLib/Core/PathUtils.cs @@ -12,7 +12,7 @@ public static class PathUtils /// /// A containing path information. /// The path with the root removed if it was present; path otherwise. - /// Unlike the class the path isn't otherwise checked for validity. + /// Unlike the class the path isn't otherwise checked for validity. public static string DropPathRoot(string path) { string result = path; diff --git a/src/ICSharpCode.SharpZipLib/Lzw/LzwInputStream.cs b/src/ICSharpCode.SharpZipLib/Lzw/LzwInputStream.cs index 3adfd7e8a..b6951c487 100644 --- a/src/ICSharpCode.SharpZipLib/Lzw/LzwInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Lzw/LzwInputStream.cs @@ -62,7 +62,7 @@ public LzwInputStream(Stream baseInputStream) } /// - /// See + /// See /// /// public override int ReadByte() diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Deflater.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Deflater.cs index 56ca20e30..8d6977014 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Deflater.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Deflater.cs @@ -157,7 +157,7 @@ public Deflater() : this(DEFAULT_COMPRESSION, false) /// the compression level, a value between NO_COMPRESSION /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION. /// - /// if lvl is out of range. + /// if lvl is out of range. public Deflater(int level) : this(level, false) { } @@ -174,7 +174,7 @@ public Deflater(int level) : this(level, false) /// beginning and the adler checksum at the end of the output. This is /// useful for the GZIP/PKZIP formats. /// - /// if lvl is out of range. + /// if lvl is out of range. public Deflater(int level, bool noZlibHeaderOrFooter) { if (level == DEFAULT_COMPRESSION) @@ -302,7 +302,7 @@ public bool IsNeedingInput /// /// the buffer containing the input data. /// - /// + /// /// if the buffer was finished() or ended(). /// public void SetInput(byte[] input) @@ -325,7 +325,7 @@ public void SetInput(byte[] input) /// /// the number of data bytes of input. /// - /// + /// /// if the buffer was Finish()ed or if previous input is still pending. /// public void SetInput(byte[] input, int offset, int count) @@ -418,10 +418,10 @@ public int Deflate(byte[] output) /// The number of compressed bytes added to the output, or 0 if either /// needsInput() or finished() returns true or length is zero. /// - /// + /// /// If Finish() was previously called. /// - /// + /// /// If offset or length don't match the array length. /// public int Deflate(byte[] output, int offset, int length) @@ -528,7 +528,7 @@ public int Deflate(byte[] output, int offset, int length) /// /// the dictionary. /// - /// + /// /// if SetInput () or Deflate () were already called or another dictionary was already set. /// public void SetDictionary(byte[] dictionary) @@ -553,7 +553,7 @@ public void SetDictionary(byte[] dictionary) /// /// The number of bytes in the dictionary. /// - /// + /// /// If SetInput () or Deflate() were already called or another dictionary was already set. /// public void SetDictionary(byte[] dictionary, int index, int count) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Inflater.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Inflater.cs index d5dc33255..9cb0a1d1d 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Inflater.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Inflater.cs @@ -580,7 +580,7 @@ public void SetDictionary(byte[] buffer) /// /// The number of bytes in the dictionary. /// - /// + /// /// No dictionary is needed. /// /// @@ -644,10 +644,10 @@ public void SetInput(byte[] buffer) /// /// The number of bytes of input to use. /// - /// + /// /// No input is needed. /// - /// + /// /// The index and/or count are wrong. /// public void SetInput(byte[] buffer, int index, int count) @@ -669,10 +669,10 @@ public void SetInput(byte[] buffer, int index, int count) /// The number of bytes written to the buffer, 0 if no further /// output can be produced. /// - /// + /// /// if buffer has length 0. /// - /// + /// /// if deflated stream is invalid. /// public int Inflate(byte[] buffer) @@ -703,13 +703,13 @@ public int Inflate(byte[] buffer) /// /// the number of bytes written to the buffer, 0 if no further output can be produced. /// - /// + /// /// if count is less than 0. /// - /// + /// /// if the index and / or count are wrong. /// - /// + /// /// if deflated stream is invalid. /// public int Inflate(byte[] buffer, int offset, int count) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs index b56732382..b5360e248 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs @@ -323,7 +323,7 @@ public ICryptoTransform CryptoTransform /// format. The "deflate" format is described in RFC 1951. /// /// This stream may form the basis for other decompression filters, such - /// as the GZipInputStream. + /// as the GZipInputStream. /// /// Author of the original java version : John Leuner. /// diff --git a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs index 209932d85..99443a06a 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs @@ -315,7 +315,7 @@ public bool RestoreAttributesOnExtract /// Get/set the Compression Level that will be used /// when creating the zip /// - public Deflater.CompressionLevel CompressionLevel + public CompressionLevel CompressionLevel { get { return compressionLevel_; } set { compressionLevel_ = value; } diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs index c830b963d..86c1bfff6 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs @@ -263,13 +263,7 @@ public ZipEntry(ZipEntry entry) /// /// Get a value indicating whether the entry has a CRC value available. /// - public bool HasCrc - { - get - { - return (known & Known.Crc) != 0; - } - } + public bool HasCrc => (known & Known.Crc) != 0; /// /// Get/Set flag indicating if entry is encrypted. @@ -278,21 +272,8 @@ public bool HasCrc /// This is an assistant that interprets the flags property. public bool IsCrypted { - get - { - return (flags & 1) != 0; - } - set - { - if (value) - { - flags |= 1; - } - else - { - flags &= ~1; - } - } + get => this.HasFlag(GeneralBitFlags.Encrypted); + set => this.SetFlag(GeneralBitFlags.Encrypted, value); } /// @@ -302,21 +283,8 @@ public bool IsCrypted /// This is an assistant that interprets the flags property. public bool IsUnicodeText { - get - { - return (flags & (int)GeneralBitFlags.UnicodeText) != 0; - } - set - { - if (value) - { - flags |= (int)GeneralBitFlags.UnicodeText; - } - else - { - flags &= ~(int)GeneralBitFlags.UnicodeText; - } - } + get => this.HasFlag(GeneralBitFlags.UnicodeText); + set => this.SetFlag(GeneralBitFlags.UnicodeText, value); } /// @@ -324,15 +292,8 @@ public bool IsUnicodeText /// internal byte CryptoCheckValue { - get - { - return cryptoCheckValue_; - } - - set - { - cryptoCheckValue_ = value; - } + get => cryptoCheckValue_; + set => cryptoCheckValue_ = value; } /// @@ -368,14 +329,8 @@ internal byte CryptoCheckValue /// public int Flags { - get - { - return flags; - } - set - { - flags = value; - } + get => flags; + set => flags = value; } /// @@ -384,14 +339,8 @@ public int Flags /// This is only valid when the entry is part of a public long ZipFileIndex { - get - { - return zipFileIndex; - } - set - { - zipFileIndex = value; - } + get => zipFileIndex; + set => zipFileIndex = value; } /// @@ -399,34 +348,18 @@ public long ZipFileIndex /// public long Offset { - get - { - return offset; - } - set - { - offset = value; - } + get => offset; + set => offset = value; } /// /// Get/Set external file attributes as an integer. - /// The values of this are operating system dependant see + /// The values of this are operating system dependent see /// HostSystem for details /// public int ExternalFileAttributes { - get - { - if ((known & Known.ExternalAttributes) == 0) - { - return -1; - } - else - { - return externalFileAttributes; - } - } + get => (known & Known.ExternalAttributes) == 0 ? -1 : externalFileAttributes; set { @@ -440,25 +373,13 @@ public int ExternalFileAttributes /// The value / 10 indicates the major version number, and /// the value mod 10 is the minor version number /// - public int VersionMadeBy - { - get - { - return (versionMadeBy & 0xff); - } - } + public int VersionMadeBy => versionMadeBy & 0xff; /// /// Get a value indicating this entry is for a DOS/Windows system. /// - public bool IsDOSEntry - { - get - { - return ((HostSystem == (int)HostSystemID.Msdos) || - (HostSystem == (int)HostSystemID.WindowsNT)); - } - } + public bool IsDOSEntry => (HostSystem == (int)HostSystemID.Msdos) + || (HostSystem == (int)HostSystemID.WindowsNT); /// /// Test the external attributes for this to @@ -481,7 +402,7 @@ private bool HasDosAttributes(int attributes) } /// - /// Gets the compatability information for the external file attribute + /// Gets the compatibility information for the external file attribute /// If the external file attributes are compatible with MS-DOS and can be read /// by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value /// will be non-zero and identify the host system on which the attributes are compatible. @@ -519,10 +440,7 @@ private bool HasDosAttributes(int attributes) /// public int HostSystem { - get - { - return (versionMadeBy >> 8) & 0xff; - } + get => (versionMadeBy >> 8) & 0xff; set { @@ -567,42 +485,26 @@ public int Version { // Return recorded version if known. if (versionToExtract != 0) - { - return versionToExtract & 0x00ff; // Only lower order byte. High order is O/S file system. - } - else - { - int result = 10; - if (AESKeySize > 0) - { - result = ZipConstants.VERSION_AES; // Ver 5.1 = AES - } - else if (CentralHeaderRequiresZip64) - { - result = ZipConstants.VersionZip64; - } - else if (CompressionMethod.Deflated == method) - { - result = 20; - } - else if (CompressionMethod.BZip2 == method) - { - result = ZipConstants.VersionBZip2; - } - else if (IsDirectory == true) - { - result = 20; - } - else if (IsCrypted == true) - { - result = 20; - } - else if (HasDosAttributes(0x08)) - { - result = 11; - } - return result; - } + // Only lower order byte. High order is O/S file system. + return versionToExtract & 0x00ff; + + if (AESKeySize > 0) + // Ver 5.1 = AES + return ZipConstants.VERSION_AES; + + if (CompressionMethod.BZip2 == method) + return ZipConstants.VersionBZip2; + + if (CentralHeaderRequiresZip64) + return ZipConstants.VersionZip64; + + if (CompressionMethod.Deflated == method || IsDirectory || IsCrypted) + return 20; + + if (HasDosAttributes(0x08)) + return 11; + + return 10; } } @@ -612,36 +514,20 @@ public int Version /// This is based on the and /// whether the compression method is supported. public bool CanDecompress - { - get - { - return (Version <= ZipConstants.VersionMadeBy) && - ((Version == 10) || - (Version == 11) || - (Version == 20) || - (Version == 45) || - (Version == 46) || - (Version == 51)) && - IsCompressionMethodSupported(); - } - } + => Version <= ZipConstants.VersionMadeBy + && (Version == 10 || Version == 11 || Version == 20 || Version == 45 || Version == 46 || Version == 51) + && IsCompressionMethodSupported(); /// /// Force this entry to be recorded using Zip64 extensions. /// - public void ForceZip64() - { - forceZip64_ = true; - } + public void ForceZip64() => forceZip64_ = true; /// /// Get a value indicating whether Zip64 extensions were forced. /// /// A value of true if Zip64 extensions have been forced on; false if not. - public bool IsZip64Forced() - { - return forceZip64_; - } + public bool IsZip64Forced() => forceZip64_; /// /// Gets a value indicating if the entry requires Zip64 extensions @@ -677,13 +563,7 @@ public bool LocalHeaderRequiresZip64 /// /// Get a value indicating whether the central directory entry requires Zip64 extensions to be stored. /// - public bool CentralHeaderRequiresZip64 - { - get - { - return LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); - } - } + public bool CentralHeaderRequiresZip64 => LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); /// /// Get/Set DosTime value. @@ -696,44 +576,40 @@ public long DosTime get { if ((known & Known.Time) == 0) - { return 0; + + var year = (uint)DateTime.Year; + var month = (uint)DateTime.Month; + var day = (uint)DateTime.Day; + var hour = (uint)DateTime.Hour; + var minute = (uint)DateTime.Minute; + var second = (uint)DateTime.Second; + + if (year < 1980) + { + year = 1980; + month = 1; + day = 1; + hour = 0; + minute = 0; + second = 0; } - else + else if (year > 2107) { - var year = (uint)DateTime.Year; - var month = (uint)DateTime.Month; - var day = (uint)DateTime.Day; - var hour = (uint)DateTime.Hour; - var minute = (uint)DateTime.Minute; - var second = (uint)DateTime.Second; - - if (year < 1980) - { - year = 1980; - month = 1; - day = 1; - hour = 0; - minute = 0; - second = 0; - } - else if (year > 2107) - { - year = 2107; - month = 12; - day = 31; - hour = 23; - minute = 59; - second = 59; - } - - return ((year - 1980) & 0x7f) << 25 | - (month << 21) | - (day << 16) | - (hour << 11) | - (minute << 5) | - (second >> 1); + year = 2107; + month = 12; + day = 31; + hour = 23; + minute = 59; + second = 59; } + + return (((year - 1980) & 0x7f) << 25) | + (month << 21) | + (day << 16) | + (hour << 11) | + (minute << 5) | + (second >> 1); } set @@ -760,10 +636,7 @@ public long DosTime /// public DateTime DateTime { - get - { - return dateTime; - } + get => dateTime; set { @@ -783,15 +656,8 @@ public DateTime DateTime /// public string Name { - get - { - return name; - } - - internal set - { - name = value; - } + get => name; + internal set => name = value; } /// @@ -801,13 +667,10 @@ internal set /// The size or -1 if unknown. /// /// Setting the size before adding an entry to an archive can help - /// avoid compatability problems with some archivers which dont understand Zip64 extensions. + /// avoid compatibility problems with some archivers which don't understand Zip64 extensions. public long Size { - get - { - return (known & Known.Size) != 0 ? (long)size : -1L; - } + get => (known & Known.Size) != 0 ? (long)size : -1L; set { size = (ulong)value; @@ -823,10 +686,7 @@ public long Size /// public long CompressedSize { - get - { - return (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; - } + get => (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; set { compressedSize = (ulong)value; @@ -837,7 +697,7 @@ public long CompressedSize /// /// Gets/Sets the crc of the uncompressed data. /// - /// + /// /// Crc is not in the range 0..0xffffffffL /// /// @@ -845,44 +705,31 @@ public long CompressedSize /// public long Crc { - get - { - return (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; - } + get => (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; set { if ((crc & 0xffffffff00000000L) != 0) - { throw new ArgumentOutOfRangeException(nameof(value)); - } + crc = (uint)value; known |= Known.Crc; } } /// - /// Gets/Sets the compression method. Only Deflated and Stored are supported. + /// Gets/Sets the compression method. /// + /// Throws exception when set if the method is not valid as per + /// /// /// The compression method for this entry /// - /// - /// public CompressionMethod CompressionMethod { - get - { - return method; - } - - set - { - if (!IsCompressionMethodSupported(value)) - { - throw new NotSupportedException("Compression method not supported"); - } - method = value; - } + get => method; + set => method = !IsCompressionMethodSupported(value) + ? throw new NotSupportedException("Compression method not supported") + : value; } /// @@ -890,18 +737,12 @@ public CompressionMethod CompressionMethod /// Returns same value as CompressionMethod except when AES encrypting, which /// places 99 in the method and places the real method in the extra data. /// - internal CompressionMethod CompressionMethodForHeader - { - get - { - return (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; - } - } + internal CompressionMethod CompressionMethodForHeader => (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; /// /// Gets/Sets the extra data. /// - /// + /// /// Extra data is longer than 64KB (0xffff) bytes. /// /// @@ -909,12 +750,9 @@ internal CompressionMethod CompressionMethodForHeader /// public byte[] ExtraData { - get - { - // TODO: This is slightly safer but less efficient. Think about whether it should change. - // return (byte[]) extra.Clone(); - return extra; - } + // TODO: This is slightly safer but less efficient. Think about whether it should change. + // return (byte[]) extra.Clone(); + get => extra; set { @@ -926,7 +764,7 @@ public byte[] ExtraData { if (value.Length > 0xffff) { - throw new System.ArgumentOutOfRangeException(nameof(value)); + throw new ArgumentOutOfRangeException(nameof(value)); } extra = new byte[value.Length]; @@ -969,62 +807,37 @@ public int AESKeySize /// AES Encryption strength for storage in extra data in entry header. /// 1 is 128 bit, 2 is 192 bit, 3 is 256 bit. /// - internal byte AESEncryptionStrength - { - get - { - return (byte)_aesEncryptionStrength; - } - } + internal byte AESEncryptionStrength => (byte)_aesEncryptionStrength; /// /// Returns the length of the salt, in bytes /// - internal int AESSaltLen - { - get - { - // Key size -> Salt length: 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. - return AESKeySize / 16; - } - } + internal int AESSaltLen => AESKeySize / 16; /// /// Number of extra bytes required to hold the AES Header fields (Salt, Pwd verify, AuthCode) /// - internal int AESOverheadSize - { - get - { - // File format: - // Bytes Content - // Variable Salt value - // 2 Password verification value - // Variable Encrypted file data - // 10 Authentication code - return 12 + AESSaltLen; - } - } + /// File format: + /// Bytes | Content + /// ---------+--------------------------- + /// Variable | Salt value + /// 2 | Password verification value + /// Variable | Encrypted file data + /// 10 | Authentication code + internal int AESOverheadSize => 12 + AESSaltLen; /// /// Number of extra bytes required to hold the encryption header fields. /// - internal int EncryptionOverheadSize - { - get - { - // Entry is not encrypted - no overhead - if (!IsCrypted) - return 0; - - // Entry is encrypted using ZipCrypto - if (_aesEncryptionStrength == 0) - return ZipConstants.CryptoHeaderSize; - - // Entry is encrypted using AES - return AESOverheadSize; - } - } + internal int EncryptionOverheadSize => + !IsCrypted + // Entry is not encrypted - no overhead + ? 0 + : _aesEncryptionStrength == 0 + // Entry is encrypted using ZipCrypto + ? ZipConstants.CryptoHeaderSize + // Entry is encrypted using AES + : AESOverheadSize; /// /// Process extra data fields updating the entry based on the contents. @@ -1155,7 +968,7 @@ private void ProcessAESExtraData(ZipExtraData extraData) /// /// Gets/Sets the entry comment. /// - /// + /// /// If comment is longer than 0xffff. /// /// @@ -1163,14 +976,11 @@ private void ProcessAESExtraData(ZipExtraData extraData) /// /// /// A comment is only available for entries when read via the class. - /// The class doesnt have the comment data available. + /// The class doesn't have the comment data available. /// public string Comment { - get - { - return comment; - } + get => comment; set { // This test is strictly incorrect as the length is in characters @@ -1179,11 +989,9 @@ public string Comment // is definitely invalid, shorter comments may also have an invalid length // where there are multi-byte characters // The full test is not possible here however as the code page to apply conversions with - // isnt available. + // isn't available. if ((value != null) && (value.Length > 0xffff)) - { throw new ArgumentOutOfRangeException(nameof(value), "cannot exceed 65535"); - } comment = value; } @@ -1200,18 +1008,8 @@ public string Comment /// The trailing slash convention should always be followed. /// public bool IsDirectory - { - get - { - int nameLength = name.Length; - bool result = - ((nameLength > 0) && - ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) || - HasDosAttributes(16) - ; - return result; - } - } + => name.Length > 0 + && (name[name.Length - 1] == '/' || name[name.Length - 1] == '\\') || HasDosAttributes(16); /// /// Get a value of true if the entry appears to be a file; false otherwise @@ -1220,22 +1018,13 @@ public bool IsDirectory /// This only takes account of DOS/Windows attributes. Other operating systems are ignored. /// For linux and others the result may be incorrect. /// - public bool IsFile - { - get - { - return !IsDirectory && !HasDosAttributes(8); - } - } + public bool IsFile => !IsDirectory && !HasDosAttributes(8); /// /// Test entry to see if data can be extracted. /// /// Returns true if data can be extracted for this entry; false otherwise. - public bool IsCompressionMethodSupported() - { - return IsCompressionMethodSupported(CompressionMethod); - } + public bool IsCompressionMethodSupported() => IsCompressionMethodSupported(CompressionMethod); #region ICloneable Members @@ -1263,10 +1052,7 @@ public object Clone() /// Gets a string representation of this ZipEntry. /// /// A readable textual representation of this - public override string ToString() - { - return name; - } + public override string ToString() => name; /// /// Test a compression method to see if this library @@ -1275,12 +1061,9 @@ public override string ToString() /// The compression method to test. /// Returns true if the compression method is supported; false otherwise public static bool IsCompressionMethodSupported(CompressionMethod method) - { - return - (method == CompressionMethod.Deflated) || - (method == CompressionMethod.Stored) || - (method == CompressionMethod.BZip2); - } + => method == CompressionMethod.Deflated + || method == CompressionMethod.Stored + || method == CompressionMethod.BZip2; /// /// Cleans a name making it conform to Zip file conventions. diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntryExtensions.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryExtensions.cs new file mode 100644 index 000000000..67b209bda --- /dev/null +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryExtensions.cs @@ -0,0 +1,28 @@ +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// General ZipEntry helper extensions + /// + public static class ZipEntryExtensions + { + /// + /// Efficiently check if a flag is set without enum un-/boxing + /// + /// + /// + /// Returns whether the flag was set + public static bool HasFlag(this ZipEntry entry, GeneralBitFlags flag) + => (entry.Flags & (int)flag) != 0; + + /// + /// Efficiently set a flag without enum un-/boxing + /// + /// + /// + /// Whether the passed flag should be set (1) or cleared (0) + public static void SetFlag(this ZipEntry entry, GeneralBitFlags flag, bool enabled = true) + => entry.Flags = enabled + ? entry.Flags | (int)flag + : entry.Flags & ~(int)flag; + } +} diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs index 32728ae5b..caabc7a80 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntryFactory.cs @@ -52,7 +52,7 @@ public enum TimeSetting /// The actual value used can be /// specified via the constructor or /// using the with the setting set - /// to which will use the when this class was constructed. + /// to which will use the when this class was constructed. /// The property can also be used to set this value. Fixed, } diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs index 8cafa687d..d64680935 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs @@ -560,7 +560,7 @@ internal ZipFile() /// Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. /// Once closed, no further instance methods should be called. /// - /// + /// /// An i/o error occurs. /// public void Close() @@ -707,7 +707,7 @@ public long Count /// /// Indexer property for ZipEntries /// - [System.Runtime.CompilerServices.IndexerNameAttribute("EntryByIndex")] + [System.Runtime.CompilerServices.IndexerName("EntryByIndex")] public ZipEntry this[int index] { get @@ -797,7 +797,7 @@ public ZipEntry GetEntry(string name) /// /// The ZipFile has already been closed /// - /// + /// /// The compression method for the entry is unknown /// /// @@ -837,7 +837,7 @@ public Stream GetInputStream(ZipEntry entry) /// /// The ZipFile has already been closed /// - /// + /// /// The compression method for the entry is unknown /// /// @@ -3295,7 +3295,7 @@ private ushort ReadLEUshort() /// /// An i/o error occurs. /// - /// + /// /// The file ends prematurely /// private uint ReadLEUint() @@ -3320,10 +3320,10 @@ private long LocateBlockWithSignature(int signature, long endLocation, int minim /// /// Search for and read the central directory of a zip file filling the entries array. /// - /// + /// /// An i/o error occurs. /// - /// + /// /// The central directory is malformed or cannot be found /// private void ReadEntries() @@ -3530,10 +3530,10 @@ private void ReadEntries() /// /// The start offset of the data. /// - /// + /// /// The stream ends prematurely /// - /// + /// /// The local header signature is invalid, the entry and central header file name lengths are different /// or the local and entry compression methods dont match /// @@ -3940,12 +3940,12 @@ public override long Position /// /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. /// - /// The sum of offset and count is larger than the buffer length. - /// Methods were called after the stream was closed. - /// The stream does not support reading. - /// buffer is null. - /// An I/O error occurs. - /// offset or count is negative. + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. public override int Read(byte[] buffer, int offset, int count) { return 0; @@ -3955,13 +3955,13 @@ public override int Read(byte[] buffer, int offset, int count) /// Sets the position within the current stream. /// /// A byte offset relative to the origin parameter. - /// A value of type indicating the reference point used to obtain the new position. + /// A value of type indicating the reference point used to obtain the new position. /// /// The new position within the current stream. /// - /// An I/O error occurs. - /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. public override long Seek(long offset, SeekOrigin origin) { return 0; @@ -3971,9 +3971,9 @@ public override long Seek(long offset, SeekOrigin origin) /// Sets the length of the current stream. /// /// The desired length of the current stream in bytes. - /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. - /// An I/O error occurs. - /// Methods were called after the stream was closed. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. public override void SetLength(long value) { } @@ -3984,12 +3984,12 @@ public override void SetLength(long value) /// An array of bytes. This method copies count bytes from buffer to the current stream. /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. /// The number of bytes to be written to the current stream. - /// An I/O error occurs. - /// The stream does not support writing. - /// Methods were called after the stream was closed. - /// buffer is null. - /// The sum of offset and count is greater than the buffer length. - /// offset or count is negative. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. public override void Write(byte[] buffer, int offset, int count) { baseStream_.Write(buffer, offset, count); @@ -4069,12 +4069,12 @@ public override int ReadByte() /// /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. /// - /// The sum of offset and count is larger than the buffer length. - /// Methods were called after the stream was closed. - /// The stream does not support reading. - /// buffer is null. - /// An I/O error occurs. - /// offset or count is negative. + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. public override int Read(byte[] buffer, int offset, int count) { lock (baseStream_) @@ -4108,12 +4108,12 @@ public override int Read(byte[] buffer, int offset, int count) /// An array of bytes. This method copies count bytes from buffer to the current stream. /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. /// The number of bytes to be written to the current stream. - /// An I/O error occurs. - /// The stream does not support writing. - /// Methods were called after the stream was closed. - /// buffer is null. - /// The sum of offset and count is greater than the buffer length. - /// offset or count is negative. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); @@ -4123,9 +4123,9 @@ public override void Write(byte[] buffer, int offset, int count) /// When overridden in a derived class, sets the length of the current stream. /// /// The desired length of the current stream in bytes. - /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. - /// An I/O error occurs. - /// Methods were called after the stream was closed. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. public override void SetLength(long value) { throw new NotSupportedException(); @@ -4135,13 +4135,13 @@ public override void SetLength(long value) /// When overridden in a derived class, sets the position within the current stream. /// /// A byte offset relative to the origin parameter. - /// A value of type indicating the reference point used to obtain the new position. + /// A value of type indicating the reference point used to obtain the new position. /// /// The new position within the current stream. /// - /// An I/O error occurs. - /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. public override long Seek(long offset, SeekOrigin origin) { long newPos = readPos_; @@ -4177,7 +4177,7 @@ public override long Seek(long offset, SeekOrigin origin) /// /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. /// - /// An I/O error occurs. + /// An I/O error occurs. public override void Flush() { // Nothing to do. @@ -4188,9 +4188,9 @@ public override void Flush() /// /// /// The current position within the stream. - /// An I/O error occurs. - /// The stream does not support seeking. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. public override long Position { get { return readPos_ - start_; } @@ -4216,8 +4216,8 @@ public override long Position /// /// /// A long value representing the length of the stream in bytes. - /// A class derived from Stream does not support seeking. - /// Methods were called after the stream was closed. + /// A class derived from Stream does not support seeking. + /// Methods were called after the stream was closed. public override long Length { get { return length_; } diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipHelperStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipHelperStream.cs index e3a9b8c0b..f32579c6c 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipHelperStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipHelperStream.cs @@ -353,7 +353,7 @@ public int ReadLEShort() /// /// An i/o error occurs. /// - /// + /// /// The file ends prematurely /// public int ReadLEInt() diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs index 095882a22..06cc95949 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs @@ -126,14 +126,15 @@ public string Password /// /// The entry can only be decompressed if the library supports the zip features required to extract it. /// See the ZipEntry Version property for more details. + /// + /// Since uses the local headers for extraction, entries with no compression combined with the + /// flag set, cannot be extracted as the end of the entry data cannot be deduced. /// public bool CanDecompressEntry - { - get - { - return (entry != null) && IsEntryCompressionMethodSupported(entry) && entry.CanDecompress; - } - } + => entry != null + && IsEntryCompressionMethodSupported(entry) + && entry.CanDecompress + && (!entry.HasFlag(GeneralBitFlags.Descriptor) || entry.CompressionMethod != CompressionMethod.Stored || entry.IsCrypted); /// /// Is the compression method for the specified entry supported? @@ -142,7 +143,7 @@ public bool CanDecompressEntry /// Uses entry.CompressionMethodForHeader so that entries of type WinZipAES will be rejected. /// /// the entry to check. - /// true if the compression methiod is supported, false if not. + /// true if the compression method is supported, false if not. private static bool IsEntryCompressionMethodSupported(ZipEntry entry) { var entryCompressionMethod = entry.CompressionMethodForHeader; @@ -481,17 +482,20 @@ public override int ReadByte() /// The maximum number of bytes to read. /// Returns the number of bytes actually read. private int ReadingNotAvailable(byte[] destination, int offset, int count) - { - throw new InvalidOperationException("Unable to read from this stream"); - } + => throw new InvalidOperationException("Unable to read from this stream"); /// /// Handle attempts to read from this entry by throwing an exception /// private int ReadingNotSupported(byte[] destination, int offset, int count) - { - throw new ZipException("The compression method for this entry is not supported"); - } + => throw new ZipException("The compression method for this entry is not supported"); + + /// + /// Handle attempts to read from this entry by throwing an exception + /// + private int StoredDescriptorEntry(byte[] destination, int offset, int count) => + throw new StreamUnsupportedException( + "The combination of Stored compression method and Descriptor flag is not possible to read using ZipInputStream"); /// /// Perform the initial read on an entry which may include @@ -503,10 +507,7 @@ private int ReadingNotSupported(byte[] destination, int offset, int count) /// The actual number of bytes read. private int InitialRead(byte[] destination, int offset, int count) { - if (!CanDecompressEntry) - { - throw new ZipException("Library cannot extract this entry. Version required is (" + entry.Version + ")"); - } + var usesDescriptor = (entry.Flags & (int)GeneralBitFlags.Descriptor) != 0; // Handle encryption if required. if (entry.IsCrypted) @@ -534,9 +535,9 @@ private int InitialRead(byte[] destination, int offset, int count) { csize -= ZipConstants.CryptoHeaderSize; } - else if ((entry.Flags & (int)GeneralBitFlags.Descriptor) == 0) + else if (!usesDescriptor) { - throw new ZipException(string.Format("Entry compressed size {0} too small for encryption", csize)); + throw new ZipException($"Entry compressed size {csize} too small for encryption"); } } else @@ -544,21 +545,32 @@ private int InitialRead(byte[] destination, int offset, int count) inputBuffer.CryptoTransform = null; } - if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0)) + if (csize > 0 || usesDescriptor) { - if ((method == CompressionMethod.Deflated) && (inputBuffer.Available > 0)) + if (method == CompressionMethod.Deflated && inputBuffer.Available > 0) { inputBuffer.SetInflaterInput(inf); } - internalReader = new ReadDataHandler(BodyRead); + // It's not possible to know how many bytes to read when using "Stored" compression (unless using encryption) + if (!entry.IsCrypted && method == CompressionMethod.Stored && usesDescriptor) + { + internalReader = StoredDescriptorEntry; + return StoredDescriptorEntry(destination, offset, count); + } + + if (!CanDecompressEntry) + { + internalReader = ReadingNotSupported; + return ReadingNotSupported(destination, offset, count); + } + + internalReader = BodyRead; return BodyRead(destination, offset, count); } - else - { - internalReader = new ReadDataHandler(ReadingNotAvailable); - return 0; - } + + internalReader = ReadingNotAvailable; + return 0; } /// diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs index abd6d727e..49db587d5 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs @@ -115,7 +115,7 @@ public void SetComment(string comment) /// /// Level specified is not supported. /// - /// + /// public void SetLevel(int level) { deflater_.SetLevel(level); @@ -212,13 +212,13 @@ private void TransformEntryName(ZipEntry entry) /// /// the entry. /// - /// + /// /// if entry passed is null. /// - /// + /// /// if an I/O error occured. /// - /// + /// /// if stream was finished /// /// @@ -226,7 +226,7 @@ private void TransformEntryName(ZipEntry entry) /// Entry name is too long
/// Finish has already been called
///
- /// + /// /// The Compression method specified for the entry is unsupported. /// public void PutNextEntry(ZipEntry entry) @@ -499,10 +499,10 @@ public void PutNextEntry(ZipEntry entry) /// /// Invalid entry field values. /// - /// + /// /// An I/O error occurs. /// - /// + /// /// No entry is active. /// public void CloseEntry() @@ -688,7 +688,7 @@ private void WriteAESHeader(ZipEntry entry) /// The offset of the first byte to write. /// The number of bytes to write. /// Archive size is invalid - /// No entry is active. + /// No entry is active. public override void Write(byte[] buffer, int offset, int count) { if (curEntry == null) @@ -764,7 +764,7 @@ private void CopyAndEncrypt(byte[] buffer, int offset, int count) /// /// This is automatically called when the stream is closed. /// - /// + /// /// An I/O error occurs. /// ///