• 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.codesigning.sign;
17 
18 import com.ohos.hapsigntool.utils.FileUtils;
19 
20 import org.bouncycastle.util.Strings;
21 
22 import java.util.Locale;
23 import java.util.zip.ZipEntry;
24 
25 /**
26  * Central directory structure
27  * further reference to <a herf="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT">Zip Format</a>
28  *
29  * @since 2023/09/14
30  */
31 public class CentralDirectory {
32     /**
33      * Byte size of all fields before "compression method" in central directory structure
34      */
35     public static final int BYTE_SIZE_BEFORE_COMPRESSION_METHOD = 10;
36 
37     /**
38      * Byte size of all fields between "compression method" and "file comment length" in central directory structure
39      */
40     public static final int BYTE_SIZE_BETWEEN_COMPRESSION_MODE_AND_FILE_SIZE = 16;
41 
42     /**
43      * Byte size of all fields between "file comment length" and
44      * "relative offset of local header" in central directory structure
45      */
46     public static final int BYTE_SIZE_BETWEEN_FILE_COMMENT_LENGTH_AND_LOCHDR_RELATIVE_OFFSET = 8;
47 
48     private final char compressionMethod;
49 
50     private final char fileNameLength;
51 
52     private final char extraFieldLength;
53 
54     private final char fileCommentLength;
55 
56     private final long relativeOffsetOfLocalHeader;
57 
58     private final byte[] fileName;
59 
CentralDirectory(Builder builder)60     public CentralDirectory(Builder builder) {
61         this.compressionMethod = builder.compressionMethod;
62         this.fileNameLength = builder.fileNameLength;
63         this.extraFieldLength = builder.extraFieldLength;
64         this.fileCommentLength = builder.fileCommentLength;
65         this.relativeOffsetOfLocalHeader = builder.relativeOffsetOfLocalHeader;
66         this.fileName = builder.fileName;
67     }
68 
69     /**
70      * Return true if entry is an executable file, i.e. abc or so
71      *
72      * @return true if entry is an executable file
73      */
isCodeFile()74     public boolean isCodeFile() {
75         return FileUtils.isRunnableFile(this.getFileName());
76     }
77 
78     /**
79      * Return true if zip entry is uncompressed
80      *
81      * @return true if zip entry is uncompressed
82      */
isUncompressed()83     public boolean isUncompressed() {
84         return this.compressionMethod == ZipEntry.STORED;
85     }
86 
getFileName()87     public String getFileName() {
88         return Strings.fromByteArray(this.fileName);
89     }
90 
getRelativeOffsetOfLocalHeader()91     public long getRelativeOffsetOfLocalHeader() {
92         return relativeOffsetOfLocalHeader;
93     }
94 
95     /**
96      * Sum byte size of three variable fields: file name, extra field, file comment
97      *
98      * @return Sum byte size of three variable fields
99      */
getFileNameLength()100     public char getFileNameLength() {
101         return fileNameLength;
102     }
103 
getExtraFieldLength()104     public char getExtraFieldLength() {
105         return extraFieldLength;
106     }
107 
108     /**
109      * Return a string representation of the object
110      *
111      * @return string representation of the object
112      */
toString()113     public String toString() {
114         return String.format(Locale.ROOT,
115             "CentralDirectory:compressionMode(%d), fileName(%s), relativeOffsetOfLocalHeader(%d), "
116                 + "fileNameLength(%d), extraFieldLength(%d), fileCommentLength(%d)", (int) this.compressionMethod,
117             this.getFileName(), this.relativeOffsetOfLocalHeader, (int) this.fileNameLength,
118             (int) this.extraFieldLength, (int) this.fileCommentLength);
119     }
120 
121     /**
122      * Builder of CentralDirectory class
123      */
124     public static class Builder {
125         private char compressionMethod;
126 
127         private char fileNameLength;
128 
129         private char extraFieldLength;
130 
131         private char fileCommentLength;
132 
133         private long relativeOffsetOfLocalHeader;
134 
135         private byte[] fileName;
136 
setCompressionMethod(char compressionMethod)137         public Builder setCompressionMethod(char compressionMethod) {
138             this.compressionMethod = compressionMethod;
139             return this;
140         }
141 
setFileNameLength(char fileNameLength)142         public Builder setFileNameLength(char fileNameLength) {
143             this.fileNameLength = fileNameLength;
144             return this;
145         }
146 
setExtraFieldLength(char extraFieldLength)147         public Builder setExtraFieldLength(char extraFieldLength) {
148             this.extraFieldLength = extraFieldLength;
149             return this;
150         }
151 
setFileCommentLength(char fileCommentLength)152         public Builder setFileCommentLength(char fileCommentLength) {
153             this.fileCommentLength = fileCommentLength;
154             return this;
155         }
156 
setRelativeOffsetOfLocalHeader(long relativeOffsetOfLocalHeader)157         public Builder setRelativeOffsetOfLocalHeader(long relativeOffsetOfLocalHeader) {
158             this.relativeOffsetOfLocalHeader = relativeOffsetOfLocalHeader;
159             return this;
160         }
161 
setFileName(byte[] fileName)162         public Builder setFileName(byte[] fileName) {
163             this.fileName = fileName;
164             return this;
165         }
166 
167         /**
168          * Create a CentralDirectory object
169          *
170          * @return a CentralDirectory object
171          */
build()172         public CentralDirectory build() {
173             return new CentralDirectory(this);
174         }
175     }
176 }
177