Repository: commons-compress
Updated Branches:
  refs/heads/master 992911d0f -> 9052f4df8


COMPRESS-416 Use signed integers for extended timestamps, per spec

Signed-off-by: Simon Spero <sesunc...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/cd1d329d
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/cd1d329d
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/cd1d329d

Branch: refs/heads/master
Commit: cd1d329dba95dae161317c123269c24282001a66
Parents: d0595b7
Author: Simon Spero <sesunc...@gmail.com>
Authored: Mon Jul 3 19:10:10 2017 -0400
Committer: Stefan Bodewig <bode...@apache.org>
Committed: Tue Jul 4 08:51:32 2017 +0200

----------------------------------------------------------------------
 .../archivers/zip/X5455_ExtendedTimestamp.java  | 24 ++++--
 .../zip/X5455_ExtendedTimestampTest.java        | 86 +++++++-------------
 2 files changed, 43 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/cd1d329d/src/main/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestamp.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestamp.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestamp.java
index 90bd750..f050874 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestamp.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestamp.java
@@ -25,14 +25,14 @@ import java.util.zip.ZipException;
 /**
  * <p>An extra field that stores additional file and directory timestamp data
  * for zip entries.   Each zip entry can include up to three timestamps
- * (modify, access, create*).  The timestamps are stored as 32 bit unsigned
+ * (modify, access, create*).  The timestamps are stored as 32 bit signed
  * integers representing seconds since UNIX epoch (Jan 1st, 1970, UTC).
  * This field improves on zip's default timestamp granularity, since it
  * allows one to store additional timestamps, and, in addition, the timestamps
  * are stored using per-second granularity (zip's default behaviour can only 
store
  * timestamps to the nearest <em>even</em> second).
  * </p><p>
- * Unfortunately, 32 (unsigned) bits can only store dates up to the year 2106,
+ * Unfortunately, 32 (signed) bits can only store dates up to the year 2037,
  * and so this extra field will eventually be obsolete.  Enjoy it while it 
lasts!
  * </p>
  * <ul>
@@ -370,7 +370,7 @@ public class X5455_ExtendedTimestamp implements 
ZipExtraField, Cloneable, Serial
      * @return modify time as java.util.Date or null.
      */
     public Date getModifyJavaTime() {
-        return modifyTime != null ? new Date(modifyTime.getValue() * 1000) : 
null;
+        return zipLongToDate(modifyTime);
     }
 
     /**
@@ -382,7 +382,11 @@ public class X5455_ExtendedTimestamp implements 
ZipExtraField, Cloneable, Serial
      * @return access time as java.util.Date or null.
      */
     public Date getAccessJavaTime() {
-        return accessTime != null ? new Date(accessTime.getValue() * 1000) : 
null;
+        return zipLongToDate(accessTime);
+    }
+
+    private static Date zipLongToDate(ZipLong unixTime) {
+        return unixTime != null ? new Date(unixTime.getIntValue() * 1000L) : 
null;
     }
 
     /**
@@ -400,7 +404,7 @@ public class X5455_ExtendedTimestamp implements 
ZipExtraField, Cloneable, Serial
      * @return create time as java.util.Date or null.
      */
     public Date getCreateJavaTime() {
-        return createTime != null ? new Date(createTime.getValue() * 1000) : 
null;
+        return zipLongToDate(createTime);
     }
 
     /**
@@ -518,10 +522,12 @@ public class X5455_ExtendedTimestamp implements 
ZipExtraField, Cloneable, Serial
     private static ZipLong dateToZipLong(final Date d) {
         if (d == null) { return null; }
 
-        final long TWO_TO_32 = 0x100000000L;
-        final long l = d.getTime() / 1000;
-        if (l >= TWO_TO_32) {
-            throw new IllegalArgumentException("Cannot set an X5455 timestamp 
larger than 2^32: " + l);
+        return unixTimeToZipLong(d.getTime() / 1000);
+    }
+
+    private static ZipLong unixTimeToZipLong(long l) {
+        if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("X5455 timestamps must fit in a 
signed 32 bit integer: " + l);
         }
         return new ZipLong(l);
     }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/cd1d329d/src/test/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestampTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestampTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestampTest.java
index 06c77d3..a0d9666 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestampTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/zip/X5455_ExtendedTimestampTest.java
@@ -50,7 +50,7 @@ public class X5455_ExtendedTimestampTest {
     private final static ZipShort X5455 = new ZipShort(0x5455);
 
     private final static ZipLong ZERO_TIME = new ZipLong(0);
-    private final static ZipLong MAX_TIME_SECONDS = new ZipLong(0xFFFFFFFFL);
+    private final static ZipLong MAX_TIME_SECONDS = new 
ZipLong(Integer.MAX_VALUE);
     private final static SimpleDateFormat DATE_FORMAT = new 
SimpleDateFormat("yyyy-MM-dd/HH:mm:ss Z");
 
     static {
@@ -142,51 +142,19 @@ public class X5455_ExtendedTimestampTest {
                     }
                     if (year >= 0) {
                         switch (year) {
-                            case 2107:
-                                if (!zipTimeUsesExtendedTimestamp) {
-                                    // Zip time is okay up to 2107.
-                                    assertEquals(year + "-01-01/00:00:02 
+0000", zipTime);
-                                }
-                                // But the X5455 data has overflowed:
-                                assertEquals("1970-11-24/17:31:45 +0000", 
modTime);
-                                assertEquals("1970-11-24/17:31:47 +0000", 
accTime);
-                                break;
-                            case 2108:
-                                if (!zipTimeUsesExtendedTimestamp) {
-                                    // Zip time is still okay at Jan 1st 
midnight (UTC) in 2108
-                                    // because we created the zip file in 
pacific time zone, so it's
-                                    // actually still 2107 in the zip file!
-                                    assertEquals(year + "-01-01/00:00:02 
+0000", zipTime);
-                                }
-                                // The X5455 data is still overflowed, of 
course:
-                                assertEquals("1971-11-24/17:31:45 +0000", 
modTime);
-                                assertEquals("1971-11-24/17:31:47 +0000", 
accTime);
-                                break;
-                            case 2109:
-                                // All three timestamps have overflowed by 
2109.
-                                if (!zipTimeUsesExtendedTimestamp) {
-                                    assertEquals("1981-01-01/00:00:02 +0000", 
zipTime);
-                                }
-                                assertEquals("1972-11-24/17:31:45 +0000", 
modTime);
-                                assertEquals("1972-11-24/17:31:47 +0000", 
accTime);
-
-                                // Hmmm.... looks like one could examine both 
DOS time
-                                // and the Unix time together to hack a nice 
workaround to
-                                // get timestamps past 2106 in a 
reverse-compatible way.
-
-                                break;
                             default:
                                 if (!zipTimeUsesExtendedTimestamp) {
-                                    // X5455 time is good from epoch (1970) to 
2106.
+                                    // X5455 time is good from epoch (1970) to 
2037.
                                     // Zip time is good from 1980 to 2107.
                                     if (year < 1980) {
                                         assertEquals("1980-01-01/08:00:00 
+0000", zipTime);
                                     } else {
                                         assertEquals(year + "-01-01/00:00:02 
+0000", zipTime);
                                     }
-                                }
+                                }if(year <2038) {
                                 assertEquals(year + "-01-01/00:00:01 +0000", 
modTime);
                                 assertEquals(year + "-01-01/00:00:03 +0000", 
accTime);
+                            }
                                 break;
                         }
                     }
@@ -235,9 +203,10 @@ public class X5455_ExtendedTimestampTest {
         cal.set(Calendar.DATE, 1);
         cal.set(Calendar.HOUR_OF_DAY, 0);
         cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
         cal.set(Calendar.MILLISECOND, 0);
-        final Date timeMillis = cal.getTime();
-        final ZipLong time = new ZipLong(timeMillis.getTime() / 1000);
+        final long timeMillis = cal.getTimeInMillis();
+        final ZipLong time = new ZipLong(timeMillis / 1000);
 
         // set too big
         try {
@@ -251,14 +220,15 @@ public class X5455_ExtendedTimestampTest {
         // get/set modify time
         xf.setModifyTime(time);
         assertEquals(time, xf.getModifyTime());
-        assertEquals(timeMillis, xf.getModifyJavaTime());
-        xf.setModifyJavaTime(timeMillis);
+        Date xfModifyJavaTime = xf.getModifyJavaTime();
+        assertEquals(timeMillis, xfModifyJavaTime.getTime());
+        xf.setModifyJavaTime(new Date(timeMillis));
         assertEquals(time, xf.getModifyTime());
-        assertEquals(timeMillis, xf.getModifyJavaTime());
+        assertEquals(timeMillis, xf.getModifyJavaTime().getTime());
         // Make sure milliseconds get zeroed out:
-        xf.setModifyJavaTime(new Date(timeMillis.getTime() + 123));
+        xf.setModifyJavaTime(new Date(timeMillis + 123));
         assertEquals(time, xf.getModifyTime());
-        assertEquals(timeMillis, xf.getModifyJavaTime());
+        assertEquals(timeMillis, xf.getModifyJavaTime().getTime());
         // Null
         xf.setModifyTime(null);
         assertNull(xf.getModifyJavaTime());
@@ -268,14 +238,14 @@ public class X5455_ExtendedTimestampTest {
         // get/set access time
         xf.setAccessTime(time);
         assertEquals(time, xf.getAccessTime());
-        assertEquals(timeMillis, xf.getAccessJavaTime());
-        xf.setAccessJavaTime(timeMillis);
+        assertEquals(timeMillis, xf.getAccessJavaTime().getTime());
+        xf.setAccessJavaTime(new Date(timeMillis));
         assertEquals(time, xf.getAccessTime());
-        assertEquals(timeMillis, xf.getAccessJavaTime());
+        assertEquals(timeMillis, xf.getAccessJavaTime().getTime());
         // Make sure milliseconds get zeroed out:
-        xf.setAccessJavaTime(new Date(timeMillis.getTime() + 123));
+        xf.setAccessJavaTime(new Date(timeMillis + 123));
         assertEquals(time, xf.getAccessTime());
-        assertEquals(timeMillis, xf.getAccessJavaTime());
+        assertEquals(timeMillis, xf.getAccessJavaTime().getTime());
         // Null
         xf.setAccessTime(null);
         assertNull(xf.getAccessJavaTime());
@@ -285,14 +255,14 @@ public class X5455_ExtendedTimestampTest {
         // get/set create time
         xf.setCreateTime(time);
         assertEquals(time, xf.getCreateTime());
-        assertEquals(timeMillis, xf.getCreateJavaTime());
-        xf.setCreateJavaTime(timeMillis);
+        assertEquals(timeMillis, xf.getCreateJavaTime().getTime());
+        xf.setCreateJavaTime(new Date(timeMillis));
         assertEquals(time, xf.getCreateTime());
-        assertEquals(timeMillis, xf.getCreateJavaTime());
+        assertEquals(timeMillis, xf.getCreateJavaTime().getTime());
         // Make sure milliseconds get zeroed out:
-        xf.setCreateJavaTime(new Date(timeMillis.getTime() + 123));
+        xf.setCreateJavaTime(new Date(timeMillis + 123));
         assertEquals(time, xf.getCreateTime());
-        assertEquals(timeMillis, xf.getCreateJavaTime());
+        assertEquals(timeMillis, xf.getCreateJavaTime().getTime());
         // Null
         xf.setCreateTime(null);
         assertNull(xf.getCreateJavaTime());
@@ -388,15 +358,15 @@ public class X5455_ExtendedTimestampTest {
         final byte[] CR_CENTRAL = {4}; // central data only dontains the CR 
flag and no actual data
 
         final byte[] MOD_ZERO = {1, 0, 0, 0, 0};
-        final byte[] MOD_MAX = {1, -1, -1, -1, -1};
+        final byte[] MOD_MAX = {1, -1, -1, -1, 0x7f};
         final byte[] AC_ZERO = {2, 0, 0, 0, 0};
-        final byte[] AC_MAX = {2, -1, -1, -1, -1};
+        final byte[] AC_MAX = {2, -1, -1, -1, 0x7f};
         final byte[] CR_ZERO = {4, 0, 0, 0, 0};
-        final byte[] CR_MAX = {4, -1, -1, -1, -1};
+        final byte[] CR_MAX = {4, -1, -1, -1, 0x7f};
         final byte[] MOD_AC_ZERO = {3, 0, 0, 0, 0, 0, 0, 0, 0};
-        final byte[] MOD_AC_MAX = {3, -1, -1, -1, -1, -1, -1, -1, -1};
+        final byte[] MOD_AC_MAX = {3, -1, -1, -1, 0x7f, -1, -1, -1, 0x7f};
         final byte[] MOD_AC_CR_ZERO = {7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-        final byte[] MOD_AC_CR_MAX = {7, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1};
+        final byte[] MOD_AC_CR_MAX = {7, -1, -1, -1, 0x7f, -1, -1, -1, 0x7f, 
-1, -1, -1, 0x7f};
 
         parseReparse(null, NULL_FLAGS, NULL_FLAGS);
         parseReparse(ZERO_TIME, MOD_ZERO, MOD_ZERO);

Reply via email to