• 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.file.attribute.FileTime;
30 import java.time.DateTimeException;
31 import java.time.Instant;
32 import java.time.LocalDateTime;
33 import java.time.ZoneId;
34 import java.util.Date;
35 import java.util.concurrent.TimeUnit;
36 
37 import static java.util.zip.ZipConstants.ENDHDR;
38 
39 import jdk.internal.misc.Unsafe;
40 
41 class ZipUtils {
42 
43     // used to adjust values between Windows and java epoch
44     private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
45 
46     // used to indicate the corresponding windows time is not available
47     public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
48 
49     // static final ByteBuffer defaultBuf = ByteBuffer.allocateDirect(0);
50     static final ByteBuffer defaultBuf = ByteBuffer.allocate(0);
51 
52     /**
53      * Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
54      */
winTimeToFileTime(long wtime)55     public static final FileTime winTimeToFileTime(long wtime) {
56         return FileTime.from(wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS,
57                              TimeUnit.MICROSECONDS);
58     }
59 
60     /**
61      * Converts FileTime to Windows time.
62      */
fileTimeToWinTime(FileTime ftime)63     public static final long fileTimeToWinTime(FileTime ftime) {
64         return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
65     }
66 
67     /**
68      * The upper bound of the 32-bit unix time, the "year 2038 problem".
69      */
70     public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff;
71 
72     /**
73      * Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime
74      */
unixTimeToFileTime(long utime)75     public static final FileTime unixTimeToFileTime(long utime) {
76         return FileTime.from(utime, TimeUnit.SECONDS);
77     }
78 
79     /**
80      * Converts FileTime to "standard Unix time".
81      */
fileTimeToUnixTime(FileTime ftime)82     public static final long fileTimeToUnixTime(FileTime ftime) {
83         return ftime.to(TimeUnit.SECONDS);
84     }
85 
86     /**
87      * Converts DOS time to Java time (number of milliseconds since epoch).
88      */
dosToJavaTime(long dtime)89     public static long dosToJavaTime(long dtime) {
90         int year = (int) (((dtime >> 25) & 0x7f) + 1980);
91         int month = (int) ((dtime >> 21) & 0x0f);
92         int day = (int) ((dtime >> 16) & 0x1f);
93         int hour = (int) ((dtime >> 11) & 0x1f);
94         int minute = (int) ((dtime >> 5) & 0x3f);
95         int second = (int) ((dtime << 1) & 0x3e);
96 
97         if (month > 0 && month < 13 && day > 0 && hour < 24 && minute < 60 && second < 60) {
98             try {
99                 LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
100                 return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond(
101                         ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS);
102             } catch (DateTimeException dte) {
103                 // ignore
104             }
105         }
106         return overflowDosToJavaTime(year, month, day, hour, minute, second);
107     }
108 
109     /*
110      * Deal with corner cases where an arguably mal-formed DOS time is used
111      */
112     @SuppressWarnings("deprecation") // Use of Date constructor
overflowDosToJavaTime(int year, int month, int day, int hour, int minute, int second)113     private static long overflowDosToJavaTime(int year, int month, int day,
114                                               int hour, int minute, int second) {
115         return new Date(year - 1900, month - 1, day, hour, minute, second).getTime();
116     }
117 
118 
119     /**
120      * Converts extended DOS time to Java time, where up to 1999 milliseconds
121      * might be encoded into the upper half of the returned long.
122      *
123      * @param xdostime the extended DOS time value
124      * @return milliseconds since epoch
125      */
extendedDosToJavaTime(long xdostime)126     public static long extendedDosToJavaTime(long xdostime) {
127         long time = dosToJavaTime(xdostime);
128         return time + (xdostime >> 32);
129     }
130 
131     /**
132      * Converts Java time to DOS time.
133      */
javaToDosTime(LocalDateTime ldt)134     private static long javaToDosTime(LocalDateTime ldt) {
135         int year = ldt.getYear() - 1980;
136         return (year << 25 |
137             ldt.getMonthValue() << 21 |
138             ldt.getDayOfMonth() << 16 |
139             ldt.getHour() << 11 |
140             ldt.getMinute() << 5 |
141             ldt.getSecond() >> 1) & 0xffffffffL;
142     }
143 
144     /**
145      * Converts Java time to DOS time, encoding any milliseconds lost
146      * in the conversion into the upper half of the returned long.
147      *
148      * @param time milliseconds since epoch
149      * @return DOS time with 2s remainder encoded into upper half
150      */
javaToExtendedDosTime(long time)151     static long javaToExtendedDosTime(long time) {
152         LocalDateTime ldt = javaEpochToLocalDateTime(time);
153         if (ldt.getYear() >= 1980) {
154             return javaToDosTime(ldt) + ((time % 2000) << 32);
155         }
156         return ZipEntry.DOSTIME_BEFORE_1980;
157     }
158 
javaEpochToLocalDateTime(long time)159     static LocalDateTime javaEpochToLocalDateTime(long time) {
160         Instant instant = Instant.ofEpochMilli(time);
161         return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
162     }
163 
164     /**
165      * Fetches unsigned 16-bit value from byte array at specified offset.
166      * The bytes are assumed to be in Intel (little-endian) byte order.
167      */
get16(byte b[], int off)168     public static final int get16(byte b[], int off) {
169         return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8);
170     }
171 
172     /**
173      * Fetches unsigned 32-bit value from byte array at specified offset.
174      * The bytes are assumed to be in Intel (little-endian) byte order.
175      */
get32(byte b[], int off)176     public static final long get32(byte b[], int off) {
177         return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
178     }
179 
180     /**
181      * Fetches signed 64-bit value from byte array at specified offset.
182      * The bytes are assumed to be in Intel (little-endian) byte order.
183      */
get64(byte b[], int off)184     public static final long get64(byte b[], int off) {
185         return get32(b, off) | (get32(b, off+4) << 32);
186     }
187 
188     /**
189      * Fetches signed 32-bit value from byte array at specified offset.
190      * The bytes are assumed to be in Intel (little-endian) byte order.
191      *
192      */
get32S(byte b[], int off)193     public static final int get32S(byte b[], int off) {
194         return (get16(b, off) | (get16(b, off+2) << 16));
195     }
196 
197     // fields access methods
CH(byte[] b, int n)198     static final int CH(byte[] b, int n) {
199         return b[n] & 0xff ;
200     }
201 
SH(byte[] b, int n)202     static final int SH(byte[] b, int n) {
203         return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
204     }
205 
LG(byte[] b, int n)206     static final long LG(byte[] b, int n) {
207         return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
208     }
209 
LL(byte[] b, int n)210     static final long LL(byte[] b, int n) {
211         return (LG(b, n)) | (LG(b, n + 4) << 32);
212     }
213 
GETSIG(byte[] b)214     static final long GETSIG(byte[] b) {
215         return LG(b, 0);
216     }
217 
218     /*
219      * File attribute compatibility types of CEN field "version made by"
220      */
221     static final int FILE_ATTRIBUTES_UNIX = 3; // Unix
222 
223     /*
224      * Base values for CEN field "version made by"
225      */
226     static final int VERSION_MADE_BY_BASE_UNIX = FILE_ATTRIBUTES_UNIX << 8; // Unix
227 
228 
229     // local file (LOC) header fields
LOCSIG(byte[] b)230     static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
LOCVER(byte[] b)231     static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
LOCFLG(byte[] b)232     static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
LOCHOW(byte[] b)233     static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
LOCTIM(byte[] b)234     static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
LOCCRC(byte[] b)235     static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
LOCSIZ(byte[] b)236     static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
LOCLEN(byte[] b)237     static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
LOCNAM(byte[] b)238     static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
LOCEXT(byte[] b)239     static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
240 
241     // extra local (EXT) header fields
EXTCRC(byte[] b)242     static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
EXTSIZ(byte[] b)243     static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
EXTLEN(byte[] b)244     static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
245 
246     // end of central directory header (END) fields
ENDSUB(byte[] b)247     static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
ENDTOT(byte[] b)248     static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
ENDSIZ(byte[] b)249     static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
ENDOFF(byte[] b)250     static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
ENDCOM(byte[] b)251     static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
ENDCOM(byte[] b, int off)252     static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
253 
254     // zip64 end of central directory recoder fields
ZIP64_ENDTOD(byte[] b)255     static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
ZIP64_ENDTOT(byte[] b)256     static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
ZIP64_ENDSIZ(byte[] b)257     static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
ZIP64_ENDOFF(byte[] b)258     static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
ZIP64_LOCOFF(byte[] b)259     static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
260 
261     // central directory header (CEN) fields
CENSIG(byte[] b, int pos)262     static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
CENVEM(byte[] b, int pos)263     static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
CENVEM_FA(byte[] b, int pos)264     static final int  CENVEM_FA(byte[] b, int pos) { return CH(b, pos + 5); } // file attribute compatibility
CENVER(byte[] b, int pos)265     static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
CENFLG(byte[] b, int pos)266     static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
CENHOW(byte[] b, int pos)267     static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
CENTIM(byte[] b, int pos)268     static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
CENCRC(byte[] b, int pos)269     static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
CENSIZ(byte[] b, int pos)270     static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
CENLEN(byte[] b, int pos)271     static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
CENNAM(byte[] b, int pos)272     static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
CENEXT(byte[] b, int pos)273     static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
CENCOM(byte[] b, int pos)274     static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
CENDSK(byte[] b, int pos)275     static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
CENATT(byte[] b, int pos)276     static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
CENATX(byte[] b, int pos)277     static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
CENATX_PERMS(byte[] b, int pos)278     static final int  CENATX_PERMS(byte[] b, int pos) { return SH(b, pos + 40);} // posix permission data
CENOFF(byte[] b, int pos)279     static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
280 
281     // The END header is followed by a variable length comment of size < 64k.
282     static final long END_MAXLEN = 0xFFFF + ENDHDR;
283     static final int READBLOCKSZ = 128;
284 
285     // Android-removed: not available on Android.
286     /*
287      * Loads zip native library, if not already laoded
288      *
289     static void loadLibrary() {
290         jdk.internal.loader.BootLoader.loadLibrary("zip");
291     }
292     */
293 
294     private static final Unsafe unsafe = Unsafe.getUnsafe();
295 
296     private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb");
297     private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset");
298 
getBufferArray(ByteBuffer byteBuffer)299     static byte[] getBufferArray(ByteBuffer byteBuffer) {
300         return (byte[]) unsafe.getReference(byteBuffer, byteBufferArrayOffset);
301     }
302 
getBufferOffset(ByteBuffer byteBuffer)303     static int getBufferOffset(ByteBuffer byteBuffer) {
304         return unsafe.getInt(byteBuffer, byteBufferOffsetOffset);
305     }
306 }
307