diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs index d5105b5ab..a6241cb0f 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs @@ -238,7 +238,7 @@ public ZipEntry(ZipEntry entry) size = entry.size; compressedSize = entry.compressedSize; crc = entry.crc; - dosTime = entry.dosTime; + dateTime = entry.DateTime; method = entry.method; comment = entry.comment; versionToExtract = entry.versionToExtract; @@ -696,7 +696,38 @@ public long DosTime } else { - return dosTime; + 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); } } @@ -704,10 +735,15 @@ public long DosTime { unchecked { - dosTime = (uint)value; + var dosTime = (uint)value; + uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); + uint min = Math.Min(59, (dosTime >> 5) & 0x3f); + uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); + uint mon = Math.Max(1, Math.Min(12, ((uint)(value >> 21) & 0xf))); + uint year = ((dosTime >> 25) & 0x7f) + 1980; + int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((value >> 16) & 0x1f))); + DateTime = new DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec, DateTimeKind.Utc); } - - known |= Known.Time; } } @@ -721,49 +757,13 @@ public DateTime DateTime { get { - uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); - uint min = Math.Min(59, (dosTime >> 5) & 0x3f); - uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); - uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); - uint year = ((dosTime >> 25) & 0x7f) + 1980; - int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); - return new System.DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec); + return dateTime; } set { - var year = (uint)value.Year; - var month = (uint)value.Month; - var day = (uint)value.Day; - var hour = (uint)value.Hour; - var minute = (uint)value.Minute; - var second = (uint)value.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; - } - - DosTime = ((year - 1980) & 0x7f) << 25 | - (month << 21) | - (day << 16) | - (hour << 11) | - (minute << 5) | - (second >> 1); + dateTime = value; + known |= Known.Time; } } @@ -1088,14 +1088,14 @@ internal void ProcessExtraData(bool localHeader) } } - DateTime = GetDateTime(extraData); + DateTime = GetDateTime(extraData) ?? DateTime; if (method == CompressionMethod.WinZipAES) { ProcessAESExtraData(extraData); } } - private DateTime GetDateTime(ZipExtraData extraData) + private DateTime? GetDateTime(ZipExtraData extraData) { // Check for NT timestamp // NOTE: Disable by default to match behavior of InfoZIP @@ -1107,22 +1107,10 @@ private DateTime GetDateTime(ZipExtraData extraData) // Check for Unix timestamp ExtendedUnixData unixData = extraData.GetData(); - if (unixData != null && - // Only apply modification time, but require all other values to be present - // This is done to match InfoZIP's behaviour - ((unixData.Include & ExtendedUnixData.Flags.ModificationTime) != 0) && - ((unixData.Include & ExtendedUnixData.Flags.AccessTime) != 0) && - ((unixData.Include & ExtendedUnixData.Flags.CreateTime) != 0)) + if (unixData != null && unixData.Include.HasFlag(ExtendedUnixData.Flags.ModificationTime)) return unixData.ModificationTime; - // Fall back to DOS time - uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); - uint min = Math.Min(59, (dosTime >> 5) & 0x3f); - uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); - uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); - uint year = ((dosTime >> 25) & 0x7f) + 1980; - int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); - return new DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec, DateTimeKind.Utc); + return null; } // For AES the method in the entry is 99, and the real compression method is in the extradata @@ -1328,7 +1316,7 @@ public static string CleanName(string name) private ulong compressedSize; private ushort versionToExtract; // Version required to extract (library handles <= 2.0) private uint crc; - private uint dosTime; + private DateTime dateTime; private CompressionMethod method = CompressionMethod.Deflated; private byte[] extra; diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEntryHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEntryHandling.cs index 2babfafd2..4b08f7519 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEntryHandling.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEntryHandling.cs @@ -195,10 +195,12 @@ public void DateAndTime() // Over the limit are set to max. ze.DateTime = new DateTime(2108, 1, 1); + ze.DosTime = ze.DosTime; Assert.AreEqual(new DateTime(2107, 12, 31, 23, 59, 58), ze.DateTime); // Under the limit are set to min. ze.DateTime = new DateTime(1906, 12, 4); + ze.DosTime = ze.DosTime; Assert.AreEqual(new DateTime(1980, 1, 1, 0, 0, 0), ze.DateTime); }