• 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.error.ZipException;
19 
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.nio.charset.StandardCharsets;
23 
24 /**
25  * resolve zip ZipEntryHeader data
26  * end of central dir signature    4 bytes  (0x06054b50)
27  * number of this disk             2 bytes
28  * number of the disk with the
29  * start of the central directory  2 bytes
30  * total number of entries in the
31  * central directory on this disk  2 bytes
32  * total number of entries in
33  * the central directory           2 bytes
34  * size of the central directory   4 bytes
35  * offset of start of central
36  * directory with respect to
37  * the starting disk number        4 bytes
38  * .ZIP file comment length        2 bytes
39  * .ZIP file comment       (variable size)
40  *
41  * @since 2023/12/02
42  */
43 public class ZipEntryHeader {
44     /**
45      * ZipEntryHeader invariable bytes length
46      */
47     public static final int HEADER_LENGTH = 30;
48 
49     /**
50      * 4 bytes , entry header signature
51      */
52     public static final int SIGNATURE = 0x04034b50;
53 
54     /**
55      * 2 bytes
56      */
57     private short version;
58 
59     /**
60      * 2 bytes
61      */
62     private short flag;
63 
64     /**
65      * 2 bytes
66      */
67     private short method;
68 
69     /**
70      * 2 bytes
71      */
72     private short lastTime;
73 
74     /**
75      * 2 bytes
76      */
77     private short lastDate;
78 
79     /**
80      * 4 bytes
81      */
82     private int crc32;
83 
84     /**
85      * 4 bytes
86      */
87     private long compressedSize;
88 
89     /**
90      * 4 bytes
91      */
92     private long unCompressedSize;
93 
94     /**
95      * 2 bytes
96      */
97     private int fileNameLength;
98 
99     /**
100      * 2 bytes
101      */
102     private int extraLength;
103 
104     /**
105      * n bytes
106      */
107     private String fileName;
108 
109     /**
110      * n bytes
111      */
112     private byte[] extraData;
113 
114     private int length;
115 
116     /**
117      * updateLength
118      */
updateLength()119     public void updateLength() {
120         length = HEADER_LENGTH + fileNameLength + extraLength;
121     }
122 
123     /**
124      * get Zip Entry Header
125      *
126      * @param bytes ZipEntryHeader bytes
127      * @return ZipEntryHeader
128      * @throws ZipException read entry header exception
129      */
getZipEntryHeader(byte[] bytes)130     public static ZipEntryHeader getZipEntryHeader(byte[] bytes) throws ZipException {
131         ZipEntryHeader entryHeader = new ZipEntryHeader();
132         ByteBuffer bf = ByteBuffer.wrap(bytes);
133         bf.order(ByteOrder.LITTLE_ENDIAN);
134         if (bf.getInt() != ZipEntryHeader.SIGNATURE) {
135             throw new ZipException("find zip entry head failed");
136         }
137         entryHeader.setVersion(bf.getShort());
138         entryHeader.setFlag(bf.getShort());
139         entryHeader.setMethod(bf.getShort());
140         entryHeader.setLastTime(bf.getShort());
141         entryHeader.setLastDate(bf.getShort());
142         entryHeader.setCrc32(bf.getInt());
143         entryHeader.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf));
144         entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf));
145         entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf));
146         entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf));
147         entryHeader.updateLength();
148         return entryHeader;
149     }
150 
151     /**
152      * set entry header name
153      *
154      * @param bytes name bytes
155      */
readFileName(byte[] bytes)156     public void readFileName(byte[] bytes) {
157         ByteBuffer bf = ByteBuffer.wrap(bytes);
158         bf.order(ByteOrder.LITTLE_ENDIAN);
159         if (fileNameLength > 0) {
160             byte[] nameBytes = new byte[fileNameLength];
161             bf.get(nameBytes);
162             this.fileName = new String(nameBytes, StandardCharsets.UTF_8);
163         }
164     }
165 
166     /**
167      * set entry header  extra
168      *
169      * @param bytes extra bytes
170      */
readExtra(byte[] bytes)171     public void readExtra(byte[] bytes) {
172         ByteBuffer bf = ByteBuffer.wrap(bytes);
173         bf.order(ByteOrder.LITTLE_ENDIAN);
174         if (extraLength > 0) {
175             byte[] extra = new byte[extraLength];
176             bf.get(extra);
177             this.extraData = extra;
178         }
179     }
180 
181     /**
182      * change Zip Entry Header to bytes
183      *
184      * @return bytes
185      */
toBytes()186     public byte[] toBytes() {
187         ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN);
188         bf.putInt(SIGNATURE);
189         bf.putShort(version);
190         bf.putShort(flag);
191         bf.putShort(method);
192         bf.putShort(lastTime);
193         bf.putShort(lastDate);
194         bf.putInt(crc32);
195         UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize);
196         UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize);
197         UnsignedDecimalUtil.setUnsignedShort(bf, fileNameLength);
198         UnsignedDecimalUtil.setUnsignedShort(bf, extraLength);
199         if (fileNameLength > 0) {
200             bf.put(fileName.getBytes(StandardCharsets.UTF_8));
201         }
202         if (extraLength > 0) {
203             bf.put(extraData);
204         }
205         return bf.array();
206     }
207 
getHeaderLength()208     public static int getHeaderLength() {
209         return HEADER_LENGTH;
210     }
211 
getSIGNATURE()212     public static int getSIGNATURE() {
213         return SIGNATURE;
214     }
215 
getVersion()216     public short getVersion() {
217         return version;
218     }
219 
setVersion(short version)220     public void setVersion(short version) {
221         this.version = version;
222     }
223 
getFlag()224     public short getFlag() {
225         return flag;
226     }
227 
setFlag(short flag)228     public void setFlag(short flag) {
229         this.flag = flag;
230     }
231 
getMethod()232     public short getMethod() {
233         return method;
234     }
235 
setMethod(short method)236     public void setMethod(short method) {
237         this.method = method;
238     }
239 
getLastTime()240     public short getLastTime() {
241         return lastTime;
242     }
243 
setLastTime(short lastTime)244     public void setLastTime(short lastTime) {
245         this.lastTime = lastTime;
246     }
247 
getLastDate()248     public short getLastDate() {
249         return lastDate;
250     }
251 
setLastDate(short lastDate)252     public void setLastDate(short lastDate) {
253         this.lastDate = lastDate;
254     }
255 
getCrc32()256     public int getCrc32() {
257         return crc32;
258     }
259 
setCrc32(int crc32)260     public void setCrc32(int crc32) {
261         this.crc32 = crc32;
262     }
263 
getCompressedSize()264     public long getCompressedSize() {
265         return compressedSize;
266     }
267 
setCompressedSize(long compressedSize)268     public void setCompressedSize(long compressedSize) {
269         this.compressedSize = compressedSize;
270     }
271 
getUnCompressedSize()272     public long getUnCompressedSize() {
273         return unCompressedSize;
274     }
275 
setUnCompressedSize(long unCompressedSize)276     public void setUnCompressedSize(long unCompressedSize) {
277         this.unCompressedSize = unCompressedSize;
278     }
279 
getFileNameLength()280     public int getFileNameLength() {
281         return fileNameLength;
282     }
283 
setFileNameLength(int fileNameLength)284     public void setFileNameLength(int fileNameLength) {
285         this.fileNameLength = fileNameLength;
286     }
287 
getExtraLength()288     public int getExtraLength() {
289         return extraLength;
290     }
291 
setExtraLength(int extraLength)292     public void setExtraLength(int extraLength) {
293         this.extraLength = extraLength;
294     }
295 
getFileName()296     public String getFileName() {
297         return fileName;
298     }
299 
setFileName(String fileName)300     public void setFileName(String fileName) {
301         this.fileName = fileName;
302     }
303 
getExtraData()304     public byte[] getExtraData() {
305         return extraData;
306     }
307 
setExtraData(byte[] extraData)308     public void setExtraData(byte[] extraData) {
309         this.extraData = extraData;
310     }
311 
getLength()312     public int getLength() {
313         return length;
314     }
315 
setLength(int length)316     public void setLength(int length) {
317         this.length = length;
318     }
319 }