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      */
 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      */
 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      */
 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      */
 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      */
 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
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      */
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      */
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      */
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 
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      */
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      */
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      */
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      */
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
198     static final int CH(byte[] b, int n) {
199         return b[n] & 0xff ;
200     }
201 
202     static final int SH(byte[] b, int n) {
203         return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
204     }
205 
206     static final long LG(byte[] b, int n) {
207         return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
208     }
209 
210     static final long LL(byte[] b, int n) {
211         return (LG(b, n)) | (LG(b, n + 4) << 32);
212     }
213 
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
230     static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
231     static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
232     static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
233     static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
234     static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
235     static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
236     static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
237     static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
238     static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
239     static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
240 
241     // extra local (EXT) header fields
242     static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
243     static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
244     static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
245 
246     // end of central directory header (END) fields
247     static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
248     static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
249     static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
250     static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
251     static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
252     static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
253 
254     // zip64 end of central directory recoder fields
255     static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
256     static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
257     static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
258     static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
259     static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
260 
261     // central directory header (CEN) fields
262     static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
263     static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
264     static final int  CENVEM_FA(byte[] b, int pos) { return CH(b, pos + 5); } // file attribute compatibility
265     static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
266     static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
267     static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
268     static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
269     static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
270     static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
271     static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
272     static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
273     static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
274     static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
275     static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
276     static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
277     static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
278     static final int  CENATX_PERMS(byte[] b, int pos) { return SH(b, pos + 40);} // posix permission data
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     /**
286      * Loads zip native library, if not already laoded
287      */
288     static void loadLibrary() {
289         jdk.internal.loader.BootLoader.loadLibrary("zip");
290     }
291 
292     private static final Unsafe unsafe = Unsafe.getUnsafe();
293 
294     private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb");
295     private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset");
296 
297     static byte[] getBufferArray(ByteBuffer byteBuffer) {
298         return (byte[]) unsafe.getReference(byteBuffer, byteBufferArrayOffset);
299     }
300 
301     static int getBufferOffset(ByteBuffer byteBuffer) {
302         return unsafe.getInt(byteBuffer, byteBufferOffsetOffset);
303     }
304 }