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