|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package java.util.zip; |
|
|
|
import java.nio.Buffer; |
|
import java.nio.ByteBuffer; |
|
import java.nio.file.attribute.FileTime; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.time.DateTimeException; |
|
import java.time.Instant; |
|
import java.time.LocalDateTime; |
|
import java.time.ZoneId; |
|
import java.util.Date; |
|
import java.util.concurrent.TimeUnit; |
|
|
|
import static java.util.zip.ZipConstants.ENDHDR; |
|
|
|
import jdk.internal.misc.Unsafe; |
|
import sun.nio.ch.DirectBuffer; |
|
|
|
class ZipUtils { |
|
|
|
|
|
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; |
|
|
|
|
|
public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE; |
|
|
|
|
|
static final ByteBuffer defaultBuf = ByteBuffer.allocate(0); |
|
|
|
|
|
|
|
*/ |
|
public static final FileTime winTimeToFileTime(long wtime) { |
|
return FileTime.from(wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, |
|
TimeUnit.MICROSECONDS); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static final long fileTimeToWinTime(FileTime ftime) { |
|
return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff; |
|
|
|
|
|
|
|
*/ |
|
public static final FileTime unixTimeToFileTime(long utime) { |
|
return FileTime.from(utime, TimeUnit.SECONDS); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static final long fileTimeToUnixTime(FileTime ftime) { |
|
return ftime.to(TimeUnit.SECONDS); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static long dosToJavaTime(long dtime) { |
|
int year = (int) (((dtime >> 25) & 0x7f) + 1980); |
|
int month = (int) ((dtime >> 21) & 0x0f); |
|
int day = (int) ((dtime >> 16) & 0x1f); |
|
int hour = (int) ((dtime >> 11) & 0x1f); |
|
int minute = (int) ((dtime >> 5) & 0x3f); |
|
int second = (int) ((dtime << 1) & 0x3e); |
|
|
|
if (month > 0 && month < 13 && day > 0 && hour < 24 && minute < 60 && second < 60) { |
|
try { |
|
LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second); |
|
return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond( |
|
ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS); |
|
} catch (DateTimeException dte) { |
|
// ignore |
|
} |
|
} |
|
return overflowDosToJavaTime(year, month, day, hour, minute, second); |
|
} |
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("deprecation") |
|
private static long overflowDosToJavaTime(int year, int month, int day, |
|
int hour, int minute, int second) { |
|
return new Date(year - 1900, month - 1, day, hour, minute, second).getTime(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static long extendedDosToJavaTime(long xdostime) { |
|
long time = dosToJavaTime(xdostime); |
|
return time + (xdostime >> 32); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static long javaToDosTime(long time) { |
|
Instant instant = Instant.ofEpochMilli(time); |
|
LocalDateTime ldt = LocalDateTime.ofInstant( |
|
instant, ZoneId.systemDefault()); |
|
int year = ldt.getYear() - 1980; |
|
if (year < 0) { |
|
return (1 << 21) | (1 << 16); |
|
} |
|
return (year << 25 | |
|
ldt.getMonthValue() << 21 | |
|
ldt.getDayOfMonth() << 16 | |
|
ldt.getHour() << 11 | |
|
ldt.getMinute() << 5 | |
|
ldt.getSecond() >> 1) & 0xffffffffL; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static long javaToExtendedDosTime(long time) { |
|
if (time < 0) { |
|
return ZipEntry.DOSTIME_BEFORE_1980; |
|
} |
|
long dostime = javaToDosTime(time); |
|
return (dostime != ZipEntry.DOSTIME_BEFORE_1980) |
|
? dostime + ((time % 2000) << 32) |
|
: ZipEntry.DOSTIME_BEFORE_1980; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final int get16(byte b[], int off) { |
|
return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final long get32(byte b[], int off) { |
|
return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static final long get64(byte b[], int off) { |
|
return get32(b, off) | (get32(b, off+4) << 32); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static final int get32S(byte b[], int off) { |
|
return (get16(b, off) | (get16(b, off+2) << 16)); |
|
} |
|
|
|
|
|
static final int CH(byte[] b, int n) { |
|
return b[n] & 0xff ; |
|
} |
|
|
|
static final int SH(byte[] b, int n) { |
|
return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8); |
|
} |
|
|
|
static final long LG(byte[] b, int n) { |
|
return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL; |
|
} |
|
|
|
static final long LL(byte[] b, int n) { |
|
return (LG(b, n)) | (LG(b, n + 4) << 32); |
|
} |
|
|
|
static final long GETSIG(byte[] b) { |
|
return LG(b, 0); |
|
} |
|
|
|
// local file (LOC) header fields |
|
static final long LOCSIG(byte[] b) { return LG(b, 0); } |
|
static final int LOCVER(byte[] b) { return SH(b, 4); } |
|
static final int LOCFLG(byte[] b) { return SH(b, 6); } |
|
static final int LOCHOW(byte[] b) { return SH(b, 8); } |
|
static final long LOCTIM(byte[] b) { return LG(b, 10);} |
|
static final long LOCCRC(byte[] b) { return LG(b, 14);} |
|
static final long LOCSIZ(byte[] b) { return LG(b, 18);} |
|
static final long LOCLEN(byte[] b) { return LG(b, 22);} |
|
static final int LOCNAM(byte[] b) { return SH(b, 26);} |
|
static final int LOCEXT(byte[] b) { return SH(b, 28);} |
|
|
|
// extra local (EXT) header fields |
|
static final long EXTCRC(byte[] b) { return LG(b, 4);} |
|
static final long EXTSIZ(byte[] b) { return LG(b, 8);} |
|
static final long EXTLEN(byte[] b) { return LG(b, 12);} |
|
|
|
// end of central directory header (END) fields |
|
static final int ENDSUB(byte[] b) { return SH(b, 8); } |
|
static final int ENDTOT(byte[] b) { return SH(b, 10);} |
|
static final long ENDSIZ(byte[] b) { return LG(b, 12);} |
|
static final long ENDOFF(byte[] b) { return LG(b, 16);} |
|
static final int ENDCOM(byte[] b) { return SH(b, 20);} |
|
static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);} |
|
|
|
// zip64 end of central directory recoder fields |
|
static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} |
|
static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} |
|
static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} |
|
static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} |
|
static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} |
|
|
|
|
|
static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } |
|
static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } |
|
static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } |
|
static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } |
|
static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} |
|
static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);} |
|
static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);} |
|
static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);} |
|
static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);} |
|
static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);} |
|
static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);} |
|
static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);} |
|
static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} |
|
static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} |
|
static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} |
|
static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} |
|
|
|
|
|
static final long END_MAXLEN = 0xFFFF + ENDHDR; |
|
static final int READBLOCKSZ = 128; |
|
|
|
|
|
|
|
*/ |
|
static void loadLibrary() { |
|
SecurityManager sm = System.getSecurityManager(); |
|
if (sm == null) { |
|
System.loadLibrary("zip"); |
|
} else { |
|
PrivilegedAction<Void> pa = () -> { System.loadLibrary("zip"); return null; }; |
|
AccessController.doPrivileged(pa); |
|
} |
|
} |
|
|
|
private static final Unsafe unsafe = Unsafe.getUnsafe(); |
|
|
|
private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb"); |
|
private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset"); |
|
|
|
static byte[] getBufferArray(ByteBuffer byteBuffer) { |
|
return (byte[]) unsafe.getObject(byteBuffer, byteBufferArrayOffset); |
|
} |
|
|
|
static int getBufferOffset(ByteBuffer byteBuffer) { |
|
return unsafe.getInt(byteBuffer, byteBufferOffsetOffset); |
|
} |
|
} |