• 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      * get Zip Entry Header
118      *
119      * @param bytes ZipEntryHeader bytes
120      * @return ZipEntryHeader
121      * @throws ZipException read entry header exception
122      */
getZipEntryHeader(byte[] bytes)123     public static ZipEntryHeader getZipEntryHeader(byte[] bytes) throws ZipException {
124         ZipEntryHeader entryHeader = new ZipEntryHeader();
125         ByteBuffer bf = ByteBuffer.wrap(bytes);
126         bf.order(ByteOrder.LITTLE_ENDIAN);
127         if (bf.getInt() != ZipEntryHeader.SIGNATURE) {
128             throw new ZipException("find zip entry head failed");
129         }
130         entryHeader.setVersion(bf.getShort());
131         entryHeader.setFlag(bf.getShort());
132         entryHeader.setMethod(bf.getShort());
133         entryHeader.setLastTime(bf.getShort());
134         entryHeader.setLastDate(bf.getShort());
135         entryHeader.setCrc32(bf.getInt());
136         entryHeader.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf));
137         entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf));
138         entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf));
139         entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf));
140         entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength());
141         return entryHeader;
142     }
143 
144     /**
145      * set entry header name
146      *
147      * @param bytes name bytes
148      */
readFileName(byte[] bytes)149     public void readFileName(byte[] bytes) {
150         ByteBuffer bf = ByteBuffer.wrap(bytes);
151         bf.order(ByteOrder.LITTLE_ENDIAN);
152         if (fileNameLength > 0) {
153             byte[] nameBytes = new byte[fileNameLength];
154             bf.get(nameBytes);
155             this.fileName = new String(nameBytes, StandardCharsets.UTF_8);
156         }
157     }
158 
159     /**
160      * set entry header  extra
161      *
162      * @param bytes extra bytes
163      */
readExtra(byte[] bytes)164     public void readExtra(byte[] bytes) {
165         ByteBuffer bf = ByteBuffer.wrap(bytes);
166         bf.order(ByteOrder.LITTLE_ENDIAN);
167         if (extraLength > 0) {
168             byte[] extra = new byte[extraLength];
169             bf.get(extra);
170             this.extraData = extra;
171         }
172     }
173 
174     /**
175      * change Zip Entry Header to bytes
176      *
177      * @return bytes
178      */
toBytes()179     public byte[] toBytes() {
180         ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN);
181         bf.putInt(SIGNATURE);
182         bf.putShort(version);
183         bf.putShort(flag);
184         bf.putShort(method);
185         bf.putShort(lastTime);
186         bf.putShort(lastDate);
187         bf.putInt(crc32);
188         UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize);
189         UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize);
190         UnsignedDecimalUtil.setUnsignedShort(bf, fileNameLength);
191         UnsignedDecimalUtil.setUnsignedShort(bf, extraLength);
192         if (fileNameLength > 0) {
193             bf.put(fileName.getBytes(StandardCharsets.UTF_8));
194         }
195         if (extraLength > 0) {
196             bf.put(extraData);
197         }
198         return bf.array();
199     }
200 
getHeaderLength()201     public static int getHeaderLength() {
202         return HEADER_LENGTH;
203     }
204 
getSIGNATURE()205     public static int getSIGNATURE() {
206         return SIGNATURE;
207     }
208 
getVersion()209     public short getVersion() {
210         return version;
211     }
212 
setVersion(short version)213     public void setVersion(short version) {
214         this.version = version;
215     }
216 
getFlag()217     public short getFlag() {
218         return flag;
219     }
220 
setFlag(short flag)221     public void setFlag(short flag) {
222         this.flag = flag;
223     }
224 
getMethod()225     public short getMethod() {
226         return method;
227     }
228 
setMethod(short method)229     public void setMethod(short method) {
230         this.method = method;
231     }
232 
getLastTime()233     public short getLastTime() {
234         return lastTime;
235     }
236 
setLastTime(short lastTime)237     public void setLastTime(short lastTime) {
238         this.lastTime = lastTime;
239     }
240 
getLastDate()241     public short getLastDate() {
242         return lastDate;
243     }
244 
setLastDate(short lastDate)245     public void setLastDate(short lastDate) {
246         this.lastDate = lastDate;
247     }
248 
getCrc32()249     public int getCrc32() {
250         return crc32;
251     }
252 
setCrc32(int crc32)253     public void setCrc32(int crc32) {
254         this.crc32 = crc32;
255     }
256 
getCompressedSize()257     public long getCompressedSize() {
258         return compressedSize;
259     }
260 
setCompressedSize(long compressedSize)261     public void setCompressedSize(long compressedSize) {
262         this.compressedSize = compressedSize;
263     }
264 
getUnCompressedSize()265     public long getUnCompressedSize() {
266         return unCompressedSize;
267     }
268 
setUnCompressedSize(long unCompressedSize)269     public void setUnCompressedSize(long unCompressedSize) {
270         this.unCompressedSize = unCompressedSize;
271     }
272 
getFileNameLength()273     public int getFileNameLength() {
274         return fileNameLength;
275     }
276 
setFileNameLength(int fileNameLength)277     public void setFileNameLength(int fileNameLength) {
278         this.fileNameLength = fileNameLength;
279     }
280 
getExtraLength()281     public int getExtraLength() {
282         return extraLength;
283     }
284 
setExtraLength(int extraLength)285     public void setExtraLength(int extraLength) {
286         this.extraLength = extraLength;
287     }
288 
getFileName()289     public String getFileName() {
290         return fileName;
291     }
292 
setFileName(String fileName)293     public void setFileName(String fileName) {
294         this.fileName = fileName;
295     }
296 
getExtraData()297     public byte[] getExtraData() {
298         return extraData;
299     }
300 
setExtraData(byte[] extraData)301     public void setExtraData(byte[] extraData) {
302         this.extraData = extraData;
303     }
304 
getLength()305     public int getLength() {
306         return length;
307     }
308 
setLength(int length)309     public void setLength(int length) {
310         this.length = length;
311     }
312 }