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) {
}
}
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);
}
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);}
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);}
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);}
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);
}
}