[Kaffe] patch for ZipEntry.java

Moses DeJong dejong at cs.umn.edu
Sun Feb 13 17:10:19 PST 2000


Here is nice little patch that fixes a problem with the "dos time"
field written out by a ZipOutputStream. I have also attached
a regression test that shows how kaffe is broken. It you apply
the patch and then run the regression test, it will pass.

Sun Feb 13 Moses DeJong  <mdejong at cs.umn.edu>

        * libraries/javalib/java/util/zip/ZipEntry.java:
        Fixed bug in the computeDosTime() and encodeDosTime()
        methods. These methods assumed a 24 hour clock but
        a 12 hour clock was actually being used.
-------------- next part --------------
Index: libraries/javalib/java/util/zip/ZipEntry.java
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/javalib/java/util/zip/ZipEntry.java,v
retrieving revision 1.9
diff -u -r1.9 ZipEntry.java
--- libraries/javalib/java/util/zip/ZipEntry.java	2000/01/10 10:41:10	1.9
+++ libraries/javalib/java/util/zip/ZipEntry.java	2000/02/13 23:56:23
@@ -55,7 +55,10 @@
     method = -1;
     extra = null;
     comment = null;
+    flag = 0;
+    version = 0;
     csize = -1;
+    offset = 0;
   }
 
   /**
@@ -65,6 +68,7 @@
   {
     name = entry.name;
     time = entry.time;
+    dosTime = entry.dosTime;
     crc  = entry.crc;
     size = entry.size;
     method = entry.method;
@@ -183,20 +187,20 @@
 
   // Encode timestamp in DOS format
   int computeDosTime(long time) {
-    time = (time + 1) & ~1L;
+    time = (time + 1) & ~1L; // Round up to even seconds.
     Calendar cal = new GregorianCalendar();
     cal.setTime(new Date(time));
     return encodeDosTime(
-	cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
-	cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR),
+	cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1,
+	cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY),
 	cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
   }
 
   int encodeDosTime(int year, int month, int day, int hour,
       int minute, int second) {
-    return (year < 1980) ? encodeDosTime(1980, 0, 1, 0, 0, 0) :
-      ((year - 1980) << 25) | ((month + 1) << 21) | (day << 16) |
-      (hour << 11) | (minute << 5) | (second >> 1);
+    return (year < 1980) ? encodeDosTime(1980, 1, 1, 0, 0, 0) :
+      ((year - 1980) << 25) | (month << 21) | (day << 16) |
+      (hour << 11) | (minute << 5) | (second >>> 1);
   }
 
   void setDosTime(int date) {
-------------- next part --------------
import java.io.*;
import java.util.zip.*;

public class DosTimeVerify {

    public static void main(String[] argv) throws Exception
    {
	ByteArrayOutputStream baos = new ByteArrayOutputStream();

	ZipOutputStream zout = new ZipOutputStream(baos);

	boolean compressed = false;

	byte[] bytes = {1, 2};

	addEntry("data", bytes, zout, compressed);

	zout.close();

	// Get the bytes written to the stream as an array
	byte[] data = baos.toByteArray();

	// Get the dosTime from offset 10

	byte[] timedate = new byte[4];
	timedate[0] = data[10];
	timedate[1] = data[11];
	timedate[2] = data[12];
	timedate[3] = data[13];

	// u4 time / date encoded in dosTime
	// 1/1/1984 12:30 and 30 seconds ( this is 0x66ddd29670L converted to dos time)
	byte[] expected_timedate = {-49, 99, 33, 8};

	boolean ok = true;

	for (int i=0; i < timedate.length; i++) {
	    if (timedate[i] != expected_timedate[i]) {
		System.out.println("timedate[" + i + "] is " +
				   timedate[i] + " expected " +
				   expected_timedate[i]);

		ok = false;
	    }
	}

	if (ok) {
	    System.out.println("OK");
	} else {

	    int int_timedate = get32(timedate, 0);
	    int int_expected_timedate = get32(expected_timedate, 0);

	    // Double cleck our assumed value

	    if (0x82163cf != int_expected_timedate) {
		System.out.println("int_expected_timedate is 0x" +
				   Integer.toHexString(int_expected_timedate) +
				   " not the expected result of 0x82163cf");
	    }

	    if (int_timedate != int_expected_timedate) {
		System.out.println("int_timedate is 0x" + Integer.toHexString(int_timedate));
		System.out.println("expected     is 0x" + Integer.toHexString(int_expected_timedate));

		System.out.println("---BINARY-SPLIT-INTO-HEX-DIGITS----------------------");

		String binary;

		System.out.print("int_timedate  ");
	    
		binary = Integer.toBinaryString(int_timedate);

		for (int i=0; i < binary.length() ; i+=4) {
		    System.out.print(binary.substring(i, i+4));
		    System.out.print(' ');
		}
		System.out.println();
		
		System.out.print("expected      ");

		binary = Integer.toBinaryString(int_expected_timedate);

		for (int i=0; i < binary.length() ; i+=4) {
		    System.out.print(binary.substring(i, i+4));
		    System.out.print(' ');
		}
		System.out.println();
	    } else {
		System.out.println("int_timedate == int_expected_timedate");
	    }

	}
    }

    public static void addEntry(String name, byte[] bytes, ZipOutputStream zout, boolean compressed)
	throws Exception
    {
	ZipEntry ze = new ZipEntry(name);

	if (compressed) {
	    ze.setMethod(ZipEntry.DEFLATED);
	} else {
	    ze.setMethod(ZipEntry.STORED);
	}
	ze.setSize( bytes.length );
	ze.setCrc( 0 );

	// 1/1/1984 12:30 and 30 seconds
	ze.setTime( 0x66ddd29670L );

	zout.putNextEntry(ze);

	zout.write(bytes);
	
	CRC32 crc = new CRC32();
	crc.update(bytes);	
	ze.setCrc( crc.getValue() );

	zout.closeEntry();
    }


    public static int get32(byte[] buf, int base) {
	int val = (int)buf[base] & 0xFF;
	val |= ((int)buf[base+1] & 0xFF) << 8;
	val |= ((int)buf[base+2] & 0xFF) << 16;
	val |= ((int)buf[base+3] & 0xFF) << 24;
	return (val);
    }

}


More information about the kaffe mailing list