• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.util.zip;
27 
28 import java.nio.ByteBuffer;
29 import java.nio.DirectByteBuffer;
30 import java.nio.file.attribute.FileTime;
31 import java.time.DateTimeException;
32 import java.time.Instant;
33 import java.time.LocalDateTime;
34 import java.time.ZoneId;
35 import java.util.Date;
36 import java.util.concurrent.TimeUnit;
37 
38 import static java.util.zip.ZipConstants.ENDHDR;
39 
40 import jdk.internal.misc.Unsafe;
41 
42 class ZipUtils {
43 
44     // used to adjust values between Windows and java epoch
45     private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
46 
47     // used to indicate the corresponding windows time is not available
48     public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
49 
50     // static final ByteBuffer defaultBuf = ByteBuffer.allocateDirect(0);
51     static final ByteBuffer defaultBuf = ByteBuffer.allocate(0);
52 
53     /**
54      * Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
55      */
winTimeToFileTime(long wtime)56     public static final FileTime winTimeToFileTime(long wtime) {
57         return FileTime.from(wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS,
58                              TimeUnit.MICROSECONDS);
59     }
60 
61     /**
62      * Converts FileTime to Windows time.
63      */
fileTimeToWinTime(FileTime ftime)64     public static final long fileTimeToWinTime(FileTime ftime) {
65         return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
66     }
67 
68     /**
69      * The upper bound of the 32-bit unix time, the "year 2038 problem".
70      */
71     public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff;
72 
73     /**
74      * Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime
75      */
unixTimeToFileTime(long utime)76     public static final FileTime unixTimeToFileTime(long utime) {
77         return FileTime.from(utime, TimeUnit.SECONDS);
78     }
79 
80     /**
81      * Converts FileTime to "standard Unix time".
82      */
fileTimeToUnixTime(FileTime ftime)83     public static final long fileTimeToUnixTime(FileTime ftime) {
84         return ftime.to(TimeUnit.SECONDS);
85     }
86 
87     /**
88      * Converts DOS time to Java time (number of milliseconds since epoch).
89      */
dosToJavaTime(long dtime)90     public static long dosToJavaTime(long dtime) {
91         int year = (int) (((dtime >> 25) & 0x7f) + 1980);
92         int month = (int) ((dtime >> 21) & 0x0f);
93         int day = (int) ((dtime >> 16) & 0x1f);
94         int hour = (int) ((dtime >> 11) & 0x1f);
95         int minute = (int) ((dtime >> 5) & 0x3f);
96         int second = (int) ((dtime << 1) & 0x3e);
97 
98         if (month > 0 && month < 13 && day > 0 && hour < 24 && minute < 60 && second < 60) {
99             try {
100                 LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
101                 return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
102                         ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
103             } catch (DateTimeException dte) {
104                 // ignore
105             }
106         }
107         return overflowDosToJavaTime(year, month, day, hour, minute, second);
108     }
109 
110     /*
111      * Deal with corner cases where an arguably mal-formed DOS time is used
112      */
113     @SuppressWarnings("deprecation") // Use of Date constructor
overflowDosToJavaTime(int year, int month, int day, int hour, int minute, int second)114     private static long overflowDosToJavaTime(int year, int month, int day,
115                                               int hour, int minute, int second) {
116         return new Date(year - 1900, month - 1, day, hour, minute, second).getTime();
117     }
118 
119 
120     /**
121      * Converts extended DOS time to Java time, where up to 1999 milliseconds
122      * might be encoded into the upper half of the returned long.
123      *
124      * @param xdostime the extended DOS time value
125      * @return milliseconds since epoch
126      */
extendedDosToJavaTime(long xdostime)127     public static long extendedDosToJavaTime(long xdostime) {
128         long time = dosToJavaTime(xdostime);
129         return time + (xdostime >> 32);
130     }
131 
132     /**
133      * Converts Java time to DOS time.
134      */
javaToDosTime(LocalDateTime ldt)135     private static long javaToDosTime(LocalDateTime ldt) {
136         int year = ldt.getYear() - 1980;
137         return (year << 25 |
138             ldt.getMonthValue() << 21 |
139             ldt.getDayOfMonth() << 16 |
140             ldt.getHour() << 11 |
141             ldt.getMinute() << 5 |
142             ldt.getSecond() >> 1) & 0xffffffffL;
143     }
144 
145     /**
146      * Converts Java time to DOS time, encoding any milliseconds lost
147      * in the conversion into the upper half of the returned long.
148      *
149      * @param time milliseconds since epoch
150      * @return DOS time with 2s remainder encoded into upper half
151      */
javaToExtendedDosTime(long time)152     static long javaToExtendedDosTime(long time) {
153         LocalDateTime ldt = javaEpochToLocalDateTime(time);
154         if (ldt.getYear() >= 1980) {
155             return javaToDosTime(ldt) + ((time % 2000) << 32);
156         }
157         return ZipEntry.DOSTIME_BEFORE_1980;
158     }
159 
javaEpochToLocalDateTime(long time)160     static LocalDateTime javaEpochToLocalDateTime(long time) {
161         Instant instant = Instant.ofEpochMilli(time);
162         return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
163     }
164 
165     /**
166      * Fetches unsigned 16-bit value from byte array at specified offset.
167      * The bytes are assumed to be in Intel (little-endian) byte order.
168      */
get16(byte b[], int off)169     public static final int get16(byte b[], int off) {
170         return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8);
171     }
172 
173     // Android-changed: don't keep CEN bytes in heap memory after initialization.
174     /**
175      * Fetches unsigned 16-bit value from buffer at current position.
176      */
get16(DirectByteBuffer bb, int pos)177     public static final int get16(DirectByteBuffer bb, int pos) {
178         return bb.getShort(pos) & 0xffff;
179     }
180 
181     /**
182      * Fetches unsigned 32-bit value from byte array at specified offset.
183      * The bytes are assumed to be in Intel (little-endian) byte order.
184      */
get32(byte b[], int off)185     public static final long get32(byte b[], int off) {
186         return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
187     }
188 
189     // Android-changed: don't keep CEN bytes in heap memory after initialization.
190     /**
191      * Fetches unsigned 32-bit value from buffer at current position.
192      */
get32(DirectByteBuffer bb, int pos)193     public static final long get32(DirectByteBuffer bb, int pos) {
194         return bb.getInt(pos) & 0xffffffffL;
195     }
196 
197     /**
198      * Fetches signed 64-bit value from byte array at specified offset.
199      * The bytes are assumed to be in Intel (little-endian) byte order.
200      */
get64(byte b[], int off)201     public static final long get64(byte b[], int off) {
202         return get32(b, off) | (get32(b, off+4) << 32);
203     }
204 
205     // Android-changed: don't keep CEN bytes in heap memory after initialization.
206     /**
207      * Fetches signed 64-bit value from byte array at specified offset.
208      * The bytes are assumed to be in Intel (little-endian) byte order.
209      */
get64(DirectByteBuffer bb, int pos)210     public static final long get64(DirectByteBuffer bb, int pos) {
211         return bb.getLong(pos) & 0xffffffffffffffffL;
212     }
213 
214     /**
215      * Fetches signed 32-bit value from byte array at specified offset.
216      * The bytes are assumed to be in Intel (little-endian) byte order.
217      *
218      */
get32S(byte b[], int off)219     public static final int get32S(byte b[], int off) {
220         return (get16(b, off) | (get16(b, off+2) << 16));
221     }
222 
223     // fields access methods
CH(byte[] b, int n)224     static final int CH(byte[] b, int n) {
225         return b[n] & 0xff ;
226     }
227 
SH(byte[] b, int n)228     static final int SH(byte[] b, int n) {
229         return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
230     }
231 
LG(byte[] b, int n)232     static final long LG(byte[] b, int n) {
233         return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
234     }
235 
LL(byte[] b, int n)236     static final long LL(byte[] b, int n) {
237         return (LG(b, n)) | (LG(b, n + 4) << 32);
238     }
239 
GETSIG(byte[] b)240     static final long GETSIG(byte[] b) {
241         return LG(b, 0);
242     }
243 
244     /*
245      * File attribute compatibility types of CEN field "version made by"
246      */
247     static final int FILE_ATTRIBUTES_UNIX = 3; // Unix
248 
249     /*
250      * Base values for CEN field "version made by"
251      */
252     static final int VERSION_MADE_BY_BASE_UNIX = FILE_ATTRIBUTES_UNIX << 8; // Unix
253 
254 
255     // local file (LOC) header fields
LOCSIG(byte[] b)256     static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
LOCVER(byte[] b)257     static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
LOCFLG(byte[] b)258     static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
LOCHOW(byte[] b)259     static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
LOCTIM(byte[] b)260     static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
LOCCRC(byte[] b)261     static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
LOCSIZ(byte[] b)262     static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
LOCLEN(byte[] b)263     static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
LOCNAM(byte[] b)264     static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
LOCEXT(byte[] b)265     static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
266 
267     // extra local (EXT) header fields
EXTCRC(byte[] b)268     static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
EXTSIZ(byte[] b)269     static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
EXTLEN(byte[] b)270     static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
271 
272     // end of central directory header (END) fields
ENDSUB(byte[] b)273     static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
ENDTOT(byte[] b)274     static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
ENDSIZ(byte[] b)275     static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
ENDOFF(byte[] b)276     static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
ENDCOM(byte[] b)277     static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
ENDCOM(byte[] b, int off)278     static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
279 
280     // zip64 end of central directory recoder fields
ZIP64_ENDTOD(byte[] b)281     static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
ZIP64_ENDTOT(byte[] b)282     static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
ZIP64_ENDSIZ(byte[] b)283     static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
ZIP64_ENDOFF(byte[] b)284     static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
ZIP64_LOCOFF(byte[] b)285     static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
286 
287     // central directory header (CEN) fields
288     // BEGIN Android-changed: don't keep CEN bytes in heap memory after initialization.
CENSIG(byte[] b, int pos)289     static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
CENVEM(byte[] b, int pos)290     static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
CENVEM_FA(byte[] b, int pos)291     static final int  CENVEM_FA(byte[] b, int pos) { return CH(b, pos + 5); } // file attribute compatibility
CENVEM_FA(DirectByteBuffer b, int pos)292     static final int  CENVEM_FA(DirectByteBuffer b, int pos) { return b.get(pos + 5); } // file attribute compatibility
CENVER(byte[] b, int pos)293     static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
CENFLG(byte[] b, int pos)294     static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
CENFLG(DirectByteBuffer b, int pos)295     static final int  CENFLG(DirectByteBuffer b, int pos) { return get16(b, pos + 8); }
CENHOW(byte[] b, int pos)296     static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
CENHOW(DirectByteBuffer b, int pos)297     static final int  CENHOW(DirectByteBuffer b, int pos) { return get16(b, pos + 10);}
CENTIM(byte[] b, int pos)298     static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
CENTIM(DirectByteBuffer b, int pos)299     static final long CENTIM(DirectByteBuffer b, int pos) { return get32(b, pos + 12);}
CENCRC(byte[] b, int pos)300     static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
CENCRC(DirectByteBuffer b, int pos)301     static final long CENCRC(DirectByteBuffer b, int pos) { return get32(b, pos + 16);}
CENSIZ(byte[] b, int pos)302     static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
CENSIZ(DirectByteBuffer b, int pos)303     static final long CENSIZ(DirectByteBuffer b, int pos) { return get32(b, pos + 20);}
CENLEN(byte[] b, int pos)304     static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
CENLEN(DirectByteBuffer b, int pos)305     static final long CENLEN(DirectByteBuffer b, int pos) { return get32(b, pos + 24);}
CENNAM(byte[] b, int pos)306     static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
CENNAM(DirectByteBuffer b, int pos)307     static final int  CENNAM(DirectByteBuffer b, int pos) { return get16(b, pos + 28);}
CENEXT(byte[] b, int pos)308     static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
CENEXT(DirectByteBuffer b, int pos)309     static final int  CENEXT(DirectByteBuffer b, int pos) { return get16(b, pos + 30);}
CENCOM(byte[] b, int pos)310     static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
CENCOM(DirectByteBuffer b, int pos)311     static final int  CENCOM(DirectByteBuffer b, int pos) { return get16(b, pos + 32);}
CENDSK(byte[] b, int pos)312     static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
CENATT(byte[] b, int pos)313     static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
CENATX(byte[] b, int pos)314     static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
CENATX_PERMS(byte[] b, int pos)315     static final int  CENATX_PERMS(byte[] b, int pos) { return SH(b, pos + 40);} // posix permission data
CENATX_PERMS(DirectByteBuffer b, int pos)316     static final int  CENATX_PERMS(DirectByteBuffer b, int pos) { return get16(b, pos + 40);} // posix permission data
CENOFF(byte[] b, int pos)317     static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
CENOFF(DirectByteBuffer b, int pos)318     static final long CENOFF(DirectByteBuffer b, int pos) { return get32(b, pos + 42);}
319     // END Android-changed: don't keep CEN bytes in heap memory after initialization.
320 
321     // The END header is followed by a variable length comment of size < 64k.
322     static final long END_MAXLEN = 0xFFFF + ENDHDR;
323     static final int READBLOCKSZ = 128;
324 
325     // Android-removed: not available on Android.
326     /*
327      * Loads zip native library, if not already laoded
328      *
329     static void loadLibrary() {
330         jdk.internal.loader.BootLoader.loadLibrary("zip");
331     }
332     */
333 
334     private static final Unsafe unsafe = Unsafe.getUnsafe();
335 
336     private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb");
337     private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset");
338 
getBufferArray(ByteBuffer byteBuffer)339     static byte[] getBufferArray(ByteBuffer byteBuffer) {
340         return (byte[]) unsafe.getReference(byteBuffer, byteBufferArrayOffset);
341     }
342 
getBufferOffset(ByteBuffer byteBuffer)343     static int getBufferOffset(ByteBuffer byteBuffer) {
344         return unsafe.getInt(byteBuffer, byteBufferOffsetOffset);
345     }
346 }
347