1 /* 2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.ohos.hapsigntool.zip; 17 18 import com.ohos.hapsigntool.utils.FileUtils; 19 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.IOException; 23 24 /** 25 * resolve zip ZipEntry data 26 * 27 * @since 2023/12/04 28 */ 29 public class ZipEntryData { 30 /** 31 * data descriptor has or not mask 32 */ 33 public static final short HAS_DATA_DESCRIPTOR_MASK = 0x08; 34 35 /** 36 * data descriptor has or not flag mask 37 */ 38 public static final short NOT_HAS_DATA_DESCRIPTOR_FLAG = 0; 39 40 private ZipEntryHeader zipEntryHeader; 41 42 private long fileOffset; 43 44 private long fileSize; 45 46 private DataDescriptor dataDescriptor; 47 48 private long length; 49 50 private EntryType type; 51 52 private byte[] data; 53 54 /** 55 * updateLength 56 */ updateLength()57 public void updateLength() { 58 zipEntryHeader.updateLength(); 59 if (data != null) { 60 length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); 61 } else { 62 length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); 63 } 64 } 65 66 /** 67 * init zip entry by file 68 * 69 * @param file zip file 70 * @param entryOffset entry start offset 71 * @param fileSize compress file size 72 * @return zip entry 73 * @throws IOException read zip exception 74 */ getZipEntry(File file, long entryOffset, long fileSize)75 public static ZipEntryData getZipEntry(File file, long entryOffset, long fileSize) 76 throws IOException { 77 try (FileInputStream input = new FileInputStream(file)) { 78 long offset = entryOffset; 79 // read entry header by file and offset. 80 byte[] headBytes = FileUtils.readInputByOffsetAndLength(input, entryOffset, ZipEntryHeader.HEADER_LENGTH); 81 ZipEntryHeader entryHeader = ZipEntryHeader.getZipEntryHeader(headBytes); 82 offset += ZipEntryHeader.HEADER_LENGTH; 83 84 // read entry file name and extra by offset. 85 if (entryHeader.getFileNameLength() > 0) { 86 byte[] fileNameBytes = FileUtils.readInputByLength(input, entryHeader.getFileNameLength()); 87 entryHeader.readFileName(fileNameBytes); 88 offset += entryHeader.getFileNameLength(); 89 } 90 91 if (entryHeader.getExtraLength() > 0) { 92 byte[] extraBytes = FileUtils.readInputByLength(input, entryHeader.getExtraLength()); 93 entryHeader.readExtra(extraBytes); 94 offset += entryHeader.getExtraLength(); 95 } 96 97 // skip file data , save file offset and size. 98 ZipEntryData entry = new ZipEntryData(); 99 entry.setFileOffset(offset); 100 entry.setFileSize(fileSize); 101 input.skip(fileSize); 102 103 if (FileUtils.isRunnableFile(entryHeader.getFileName())) { 104 entry.setType(EntryType.RUNNABLE_FILE); 105 } else if (FileUtils.BIT_MAP_FILENAME.equals(entryHeader.getFileName())) { 106 entry.setType(EntryType.BIT_MAP); 107 } else { 108 entry.setType(EntryType.RESOURCE_FILE); 109 } 110 111 long entryLength = entryHeader.getLength() + fileSize; 112 short flag = entryHeader.getFlag(); 113 // set desc null flag 114 boolean hasDesc = (flag & HAS_DATA_DESCRIPTOR_MASK) != NOT_HAS_DATA_DESCRIPTOR_FLAG; 115 if (hasDesc) { 116 // if entry has data descriptor, read entry data descriptor. 117 byte[] desBytes = FileUtils.readInputByLength(input, DataDescriptor.DES_LENGTH); 118 DataDescriptor dataDesc = DataDescriptor.getDataDescriptor(desBytes); 119 entryLength += DataDescriptor.DES_LENGTH; 120 entry.setDataDescriptor(dataDesc); 121 } 122 entry.setZipEntryHeader(entryHeader); 123 entry.setLength(entryLength); 124 return entry; 125 } 126 } 127 setZipEntryHeader(ZipEntryHeader zipEntryHeader)128 public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { 129 this.zipEntryHeader = zipEntryHeader; 130 } 131 getZipEntryHeader()132 public ZipEntryHeader getZipEntryHeader() { 133 return zipEntryHeader; 134 } 135 getDataDescriptor()136 public DataDescriptor getDataDescriptor() { 137 return dataDescriptor; 138 } 139 setDataDescriptor(DataDescriptor dataDescriptor)140 public void setDataDescriptor(DataDescriptor dataDescriptor) { 141 this.dataDescriptor = dataDescriptor; 142 } 143 getFileOffset()144 public long getFileOffset() { 145 return fileOffset; 146 } 147 setFileOffset(long fileOffset)148 public void setFileOffset(long fileOffset) { 149 this.fileOffset = fileOffset; 150 } 151 getFileSize()152 public long getFileSize() { 153 return fileSize; 154 } 155 setFileSize(long fileSize)156 public void setFileSize(long fileSize) { 157 this.fileSize = fileSize; 158 } 159 getLength()160 public long getLength() { 161 return length; 162 } 163 setLength(long length)164 public void setLength(long length) { 165 this.length = length; 166 } 167 getData()168 public byte[] getData() { 169 return data; 170 } 171 setData(byte[] data)172 public void setData(byte[] data) { 173 this.data = data; 174 } 175 getType()176 public EntryType getType() { 177 return type; 178 } 179 setType(EntryType type)180 public void setType(EntryType type) { 181 this.type = type; 182 } 183 }