• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }