1602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel/* 2602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Licensed to the Apache Software Foundation (ASF) under one or more 3602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * contributor license agreements. See the NOTICE file distributed with 4602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * this work for additional information regarding copyright ownership. 5602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * The ASF licenses this file to You under the Apache License, Version 2.0 6602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * (the "License"); you may not use this file except in compliance with 7602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * the License. You may obtain a copy of the License at 8602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * 9602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * http://www.apache.org/licenses/LICENSE-2.0 10602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * 11602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Unless required by applicable law or agreed to in writing, software 12602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * distributed under the License is distributed on an "AS IS" BASIS, 13602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * See the License for the specific language governing permissions and 15602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * limitations under the License. 16602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */ 17602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel/* Apache Harmony HEADER because the code in this class comes mostly from ZipFile, ZipEntry and 18602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * ZipConstants from android libcore. 19602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */ 20602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 21602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselpackage android.support.multidex; 22602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 23602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.IOException; 24602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.nio.ByteBuffer; 25602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.nio.charset.Charset; 26602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.Calendar; 27602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.GregorianCalendar; 28602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.zip.ZipEntry; 29602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.zip.ZipException; 30602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 31602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselclass ZipEntryReader { 32602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel static final Charset UTF_8 = Charset.forName("UTF-8"); 33602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel /** 34602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * General Purpose Bit Flags, Bit 0. 35602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * If set, indicates that the file is encrypted. 36602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */ 37602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel private static final int GPBF_ENCRYPTED_FLAG = 1 << 0; 38602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 39602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel /** 40602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Supported General Purpose Bit Flags Mask. 41602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Bit mask of bits not supported. 42602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Note: The only bit that we will enforce at this time 43602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * is the encrypted bit. Although other bits are not supported, 44602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * we must not enforce them as this could break some legitimate 45602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * use cases (See http://b/8617715). 46602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */ 47602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel private static final int GPBF_UNSUPPORTED_MASK = GPBF_ENCRYPTED_FLAG; 48602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel private static final long CENSIG = 0x2014b50; 49602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 50602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel static ZipEntry readEntry(ByteBuffer in) throws IOException { 51602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 52602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int sig = in.getInt(); 53602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel if (sig != CENSIG) { 54602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel throw new ZipException("Central Directory Entry not found"); 55602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 56602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 57602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel in.position(8); 58602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int gpbf = in.getShort() & 0xffff; 59602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 60602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel if ((gpbf & GPBF_UNSUPPORTED_MASK) != 0) { 61602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel throw new ZipException("Invalid General Purpose Bit Flag: " + gpbf); 62602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 63602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 64602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int compressionMethod = in.getShort() & 0xffff; 65602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int time = in.getShort() & 0xffff; 66602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int modDate = in.getShort() & 0xffff; 67602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 68602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel // These are 32-bit values in the file, but 64-bit fields in this object. 69602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel long crc = ((long) in.getInt()) & 0xffffffffL; 70602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel long compressedSize = ((long) in.getInt()) & 0xffffffffL; 71602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel long size = ((long) in.getInt()) & 0xffffffffL; 72602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 73602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int nameLength = in.getShort() & 0xffff; 74602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int extraLength = in.getShort() & 0xffff; 75602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel int commentByteCount = in.getShort() & 0xffff; 76602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 77602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel // This is a 32-bit value in the file, but a 64-bit field in this object. 78602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel in.position(42); 79602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel long localHeaderRelOffset = ((long) in.getInt()) & 0xffffffffL; 80602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 81602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel byte[] nameBytes = new byte[nameLength]; 82602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel in.get(nameBytes, 0, nameBytes.length); 83602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel String name = new String(nameBytes, 0, nameBytes.length, UTF_8); 84602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 85602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel ZipEntry entry = new ZipEntry(name); 86602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setMethod(compressionMethod); 87602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setTime(getTime(time, modDate)); 88602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 89602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setCrc(crc); 90602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setCompressedSize(compressedSize); 91602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setSize(size); 92602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 93602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel // The RI has always assumed UTF-8. (If GPBF_UTF8_FLAG isn't set, the encoding is 94602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel // actually IBM-437.) 95602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel if (commentByteCount > 0) { 96602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel byte[] commentBytes = new byte[commentByteCount]; 97602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel in.get(commentBytes, 0, commentByteCount); 98602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setComment(new String(commentBytes, 0, commentBytes.length, UTF_8)); 99602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 100602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 101602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel if (extraLength > 0) { 102602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel byte[] extra = new byte[extraLength]; 103602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel in.get(extra, 0, extraLength); 104602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel entry.setExtra(extra); 105602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 106602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 107602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel return entry; 108602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 109602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 110602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 111602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel private static long getTime(int time, int modDate) { 112602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel GregorianCalendar cal = new GregorianCalendar(); 113602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel cal.set(Calendar.MILLISECOND, 0); 114602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel cal.set(1980 + ((modDate >> 9) & 0x7f), ((modDate >> 5) & 0xf) - 1, 115602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel modDate & 0x1f, (time >> 11) & 0x1f, (time >> 5) & 0x3f, 116602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel (time & 0x1f) << 1); 117602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel return cal.getTime().getTime(); 118602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel } 119602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel 120602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel} 121