• 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 java.nio.ByteBuffer;
19 import java.nio.ByteOrder;
20 import java.util.Optional;
21 
22 /**
23  * resolve zip EndOfCentralDirectory data
24  * EndOfCentralDirectory format for:
25  * end of central dir signature    4 bytes  (0x06054b50)
26  * number of this disk             2 bytes
27  * number of the disk with the
28  * start of the central directory  2 bytes
29  * total number of entries in the
30  * central directory on this disk  2 bytes
31  * total number of entries in
32  * the central directory           2 bytes
33  * size of the central directory   4 bytes
34  * offset of start of central
35  * directory with respect to
36  * the starting disk number        4 bytes
37  * .ZIP file comment length        2 bytes
38  * .ZIP file comment       (variable size)
39  *
40  * @since 2023/12/04
41  */
42 public class EndOfCentralDirectory {
43     /**
44      * EndOfCentralDirectory invariable bytes length
45      */
46     public static final int EOCD_LENGTH = 22;
47 
48     /**
49      * 4 bytes , central directory signature
50      */
51     public static final int SIGNATURE = 0x06054b50;
52 
53     /**
54      * 2 bytes
55      */
56     private int diskNum;
57 
58     /**
59      * 2 bytes
60      */
61     private int cDStartDiskNum;
62 
63     /**
64      * 2 bytes
65      */
66     private int thisDiskCDNum;
67 
68     /**
69      * 2 bytes
70      */
71     private int cDTotal;
72 
73     /**
74      * 4 bytes
75      */
76     private long cDSize;
77 
78     /**
79      * 4 bytes
80      */
81     private long offset;
82 
83     /**
84      * 2 bytes
85      */
86     private int commentLength;
87 
88     /**
89      * n bytes
90      */
91     private byte[] comment;
92 
93     private int length;
94 
95     /**
96      * init End Of Central Directory, default offset is 0
97      *
98      * @param bytes End Of Central Directory bytes
99      * @return End Of Central Directory
100      */
getEOCDByBytes(byte[] bytes)101     public static Optional<EndOfCentralDirectory> getEOCDByBytes(byte[] bytes) {
102         return getEOCDByBytes(bytes, 0);
103     }
104 
105     /**
106      * init End Of Central Directory
107      *
108      * @param bytes End Of Central Directory bytes
109      * @param offset offset
110      * @return End Of Central Directory
111      */
getEOCDByBytes(byte[] bytes, int offset)112     public static Optional<EndOfCentralDirectory> getEOCDByBytes(byte[] bytes, int offset) {
113         EndOfCentralDirectory eocd = new EndOfCentralDirectory();
114         int remainingDataLen = bytes.length - offset;
115         if (remainingDataLen < EOCD_LENGTH) {
116             return Optional.empty();
117         }
118         ByteBuffer bf = ByteBuffer.wrap(bytes, offset, remainingDataLen);
119         bf.order(ByteOrder.LITTLE_ENDIAN);
120         if (bf.getInt() != SIGNATURE) {
121             return Optional.empty();
122         }
123         eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf));
124         eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf));
125         eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf));
126         eocd.setCDTotal(UnsignedDecimalUtil.getUnsignedShort(bf));
127         eocd.setCDSize(UnsignedDecimalUtil.getUnsignedInt(bf));
128         eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf));
129         eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf));
130         if (bf.remaining() != eocd.getCommentLength()) {
131             return Optional.empty();
132         }
133         if (eocd.getCommentLength() > 0) {
134             byte[] readComment = new byte[eocd.getCommentLength()];
135             bf.get(readComment);
136             eocd.setComment(readComment);
137         }
138         eocd.setLength(EOCD_LENGTH + eocd.getCommentLength());
139         if (bf.remaining() != 0) {
140             return Optional.empty();
141         }
142         return Optional.of(eocd);
143     }
144 
145     /**
146      * change End Of Central Directory to bytes
147      *
148      * @return bytes
149      */
toBytes()150     public byte[] toBytes() {
151         ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN);
152         bf.putInt(SIGNATURE);
153         UnsignedDecimalUtil.setUnsignedShort(bf, diskNum);
154         UnsignedDecimalUtil.setUnsignedShort(bf, cDStartDiskNum);
155         UnsignedDecimalUtil.setUnsignedShort(bf, thisDiskCDNum);
156         UnsignedDecimalUtil.setUnsignedShort(bf, cDTotal);
157         UnsignedDecimalUtil.setUnsignedInt(bf, cDSize);
158         UnsignedDecimalUtil.setUnsignedInt(bf, offset);
159         UnsignedDecimalUtil.setUnsignedShort(bf, commentLength);
160         if (commentLength > 0) {
161             bf.put(comment);
162         }
163         return bf.array();
164     }
165 
getEocdLength()166     public static int getEocdLength() {
167         return EOCD_LENGTH;
168     }
169 
getSIGNATURE()170     public static int getSIGNATURE() {
171         return SIGNATURE;
172     }
173 
getDiskNum()174     public int getDiskNum() {
175         return diskNum;
176     }
177 
setDiskNum(int diskNum)178     public void setDiskNum(int diskNum) {
179         this.diskNum = diskNum;
180     }
181 
getcDStartDiskNum()182     public int getcDStartDiskNum() {
183         return cDStartDiskNum;
184     }
185 
setcDStartDiskNum(int cDStartDiskNum)186     public void setcDStartDiskNum(int cDStartDiskNum) {
187         this.cDStartDiskNum = cDStartDiskNum;
188     }
189 
getThisDiskCDNum()190     public int getThisDiskCDNum() {
191         return thisDiskCDNum;
192     }
193 
setThisDiskCDNum(int thisDiskCDNum)194     public void setThisDiskCDNum(int thisDiskCDNum) {
195         this.thisDiskCDNum = thisDiskCDNum;
196     }
197 
getCDTotal()198     public int getCDTotal() {
199         return cDTotal;
200     }
201 
setCDTotal(int cDTotal)202     public void setCDTotal(int cDTotal) {
203         this.cDTotal = cDTotal;
204     }
205 
getCDSize()206     public long getCDSize() {
207         return cDSize;
208     }
209 
setCDSize(long cDSize)210     public void setCDSize(long cDSize) {
211         this.cDSize = cDSize;
212     }
213 
getOffset()214     public long getOffset() {
215         return offset;
216     }
217 
setOffset(long offset)218     public void setOffset(long offset) {
219         this.offset = offset;
220     }
221 
getCommentLength()222     public int getCommentLength() {
223         return commentLength;
224     }
225 
setCommentLength(int commentLength)226     public void setCommentLength(int commentLength) {
227         this.commentLength = commentLength;
228     }
229 
getComment()230     public byte[] getComment() {
231         return comment;
232     }
233 
setComment(byte[] comment)234     public void setComment(byte[] comment) {
235         this.comment = comment;
236     }
237 
getLength()238     public int getLength() {
239         return length;
240     }
241 
setLength(int length)242     public void setLength(int length) {
243         this.length = length;
244     }
245 }