• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef OHOS_ABILITY_BASE_ZIP_FILE_H
17 #define OHOS_ABILITY_BASE_ZIP_FILE_H
18 
19 #include <memory>
20 #include <set>
21 #include <string>
22 #include <unordered_map>
23 #include <vector>
24 
25 #include "file_mapper.h"
26 #include "unzip.h"
27 
28 namespace OHOS {
29 namespace AbilityBase {
30 class ZipFileReader;
31 struct CentralDirEntry;
32 struct ZipEntry;
33 using ZipPos = ZPOS64_T;
34 using ZipEntryMap = std::unordered_map<std::string, ZipEntry>;
35 using BytePtr = Byte *;
36 
37 // Local file header: descript in APPNOTE-6.3.4
38 //    local file header signature     4 bytes  (0x04034b50)
39 //    version needed to extract       2 bytes
40 //    general purpose bit flag        2 bytes
41 //    compression method              2 bytes  10
42 //    last mod file time              2 bytes
43 //    last mod file date              2 bytes
44 //    crc-32                          4 bytes
45 //    compressed size                 4 bytes  22
46 //    uncompressed size               4 bytes
47 //    file name length                2 bytes
48 //    extra field length              2 bytes  30
49 struct __attribute__((packed)) LocalHeader {
50     uint32_t signature = 0;
51     uint16_t versionNeeded = 0;
52     uint16_t flags = 0;
53     uint16_t compressionMethod = 0;
54     uint16_t modifiedTime = 0;
55     uint16_t modifiedDate = 0;
56     uint32_t crc = 0;
57     uint32_t compressedSize = 0;
58     uint32_t uncompressedSize = 0;
59     uint16_t nameSize = 0;
60     uint16_t extraSize = 0;
61 };
62 
63 // central file header
64 //    Central File header:
65 //    central file header signature   4 bytes  (0x02014b50)
66 //    version made by                 2 bytes
67 //    version needed to extract       2 bytes
68 //    general purpose bit flag        2 bytes  10
69 //    compression method              2 bytes
70 //    last mod file time              2 bytes
71 //    last mod file date              2 bytes
72 //    crc-32                          4 bytes  20
73 //    compressed size                 4 bytes
74 //    uncompressed size               4 bytes
75 //    file name length                2 bytes  30
76 //    extra field length              2 bytes
77 //    file comment length             2 bytes
78 //    disk number start               2 bytes
79 //    internal file attributes        2 bytes
80 //    external file attributes        4 bytes
81 //    relative offset of local header 4 bytes 46byte
82 struct __attribute__((packed)) CentralDirEntry {
83     uint32_t signature = 0;
84     uint16_t versionMade = 0;
85     uint16_t versionNeeded = 0;
86     uint16_t flags = 0;  // general purpose bit flag
87     uint16_t compressionMethod = 0;
88     uint16_t modifiedTime = 0;
89     uint16_t modifiedDate = 0;
90     uint32_t crc = 0;
91     uint32_t compressedSize = 0;
92     uint32_t uncompressedSize = 0;
93     uint16_t nameSize = 0;
94     uint16_t extraSize = 0;
95     uint16_t commentSize = 0;
96     uint16_t diskNumStart = 0;
97     uint16_t internalAttr = 0;
98     uint32_t externalAttr = 0;
99     uint32_t localHeaderOffset = 0;
100 };
101 
102 // end of central directory packed structure
103 //    end of central dir signature    4 bytes  (0x06054b50)
104 //    number of this disk             2 bytes
105 //    number of the disk with the
106 //    start of the central directory  2 bytes
107 //    total number of entries in the
108 //    central directory on this disk  2 bytes
109 //    total number of entries in
110 //    the central directory           2 bytes
111 //    size of the central directory   4 bytes
112 //    offset of start of central
113 //    directory with respect to
114 //    the starting disk number        4 bytes
115 //    .ZIP file comment length        2 bytes
116 struct __attribute__((packed)) EndDir {
117     uint32_t signature = 0;
118     uint16_t numDisk = 0;
119     uint16_t startDiskOfCentralDir = 0;
120     uint16_t totalEntriesInThisDisk = 0;
121     uint16_t totalEntries = 0;
122     uint32_t sizeOfCentralDir = 0;
123     uint32_t offset = 0;
124     uint16_t commentLen = 0;
125 };
126 
127 // Data descriptor:
128 //    data descriptor signature       4 bytes  (0x06054b50)
129 //    crc-32                          4 bytes
130 //    compressed size                 4 bytes
131 //    uncompressed size               4 bytes
132 // This descriptor MUST exist if bit 3 of the general purpose bit flag is set (see below).
133 // It is byte aligned and immediately follows the last byte of compressed data.
134 struct __attribute__((packed)) DataDesc {
135     uint32_t signature = 0;
136     uint32_t crc = 0;
137     uint32_t compressedSize = 0;
138     uint32_t uncompressedSize = 0;
139 };
140 
141 struct ZipEntry {
142     ZipEntry() = default;
143     explicit ZipEntry(const CentralDirEntry &centralEntry);
144     ~ZipEntry() = default;  // for CodeDEX warning
145 
146     uint16_t compressionMethod = 0;
147     uint32_t uncompressedSize = 0;
148     uint32_t compressedSize = 0;
149     uint32_t localHeaderOffset = 0;
150     uint32_t crc = 0;
151     uint16_t flags = 0;
152     uint16_t modifiedTime = 0;
153     uint16_t modifiedDate = 0;
154     std::string fileName;
155 };
156 
157 struct DirTreeNode {
158     std::unordered_map<std::string, std::shared_ptr<DirTreeNode>> children;
159 };
160 
161 // zip file extract class for bundle format.
162 class ZipFile {
163 public:
164     explicit ZipFile(const std::string &pathName);
165     ~ZipFile();
166     /**
167      * @brief Open zip file.
168      * @return Returns true if the zip file is successfully opened; returns false otherwise.
169      */
170     bool Open();
171     /**
172      * @brief Close zip file.
173      */
174     void Close();
175     /**
176      * @brief Set this zip content start offset and length in the zip file form pathName.
177      * @param start Indicates the zip content location start position.
178      * @param length Indicates the zip content length.
179      */
180     void SetContentLocation(const ZipPos start, const size_t length);
181     /**
182      * @brief Get all entries in the zip file.
183      * @param start Indicates the zip content location start position.
184      * @param length Indicates the zip content length.
185      * @return Returns the ZipEntryMap object cotain all entries.
186      */
187     const ZipEntryMap &GetAllEntries() const;
188     /**
189      * @brief Has entry by name.
190      * @param entryName Indicates the entry name.
191      * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
192      */
193     bool HasEntry(const std::string &entryName) const;
194 
195     bool IsDirExist(const std::string &dir) const;
196     void GetAllFileList(const std::string &srcPath, std::vector<std::string> &assetList);
197     void GetChildNames(const std::string &srcPath, std::set<std::string> &fileSet);
198 
199     /**
200      * @brief Get entry by name.
201      * @param entryName Indicates the entry name.
202      * @param resultEntry Indicates the obtained ZipEntry object.
203      * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
204      */
205     bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const;
206     /**
207      * @brief Get data relative offset for file.
208      * @param file Indicates the entry name.
209      * @param offset Indicates the obtained offset.
210      * @param length Indicates the length.
211      * @return Returns true if this function is successfully called; returns false otherwise.
212      */
213     bool GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const;
214     /**
215      * @brief Get data relative offset for file.
216      * @param file Indicates the entry name.
217      * @param dest Indicates the obtained ostream object.
218      * @return Returns true if file is successfully extracted; returns false otherwise.
219      */
220     bool ExtractFile(const std::string &file, std::ostream &dest) const;
221 
222     bool ExtractFileFromMMap(const std::string &file, void *mmapDataPtr,
223         std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const;
224 
225     std::unique_ptr<FileMapper> CreateFileMapper(const std::string &fileName, FileMapperType type) const;
226     bool ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
227         size_t &len) const;
228 private:
229     bool GetDataOffsetRelative(const ZipEntry &zipEntry, ZipPos &offset, uint32_t &length) const;
230     /**
231      * @brief Check the EndDir object.
232      * @param endDir Indicates the EndDir object to check.
233      * @return Returns true if  successfully checked; returns false otherwise.
234      */
235     bool CheckEndDir(const EndDir &endDir) const;
236     /**
237      * @brief Parse the EndDir.
238      * @return Returns true if  successfully Parsed; returns false otherwise.
239      */
240     bool ParseEndDirectory();
241     /**
242      * @brief Parse one entry.
243      * @return Returns true if successfully parsed; returns false otherwise.
244      */
245     bool ParseOneEntry(uint8_t* &entryPtr);
246     void AddEntryToTree(const std::string &fileName);
247     /**
248      * @brief Parse all Entries.
249      * @return Returns true if successfully parsed; returns false otherwise.
250      */
251     bool ParseAllEntries();
252     /**
253      * @brief Get LocalHeader object size.
254      * @param nameSize Indicates the nameSize.
255      * @param extraSize Indicates the extraSize.
256      * @return Returns size of LocalHeader.
257      */
258     size_t GetLocalHeaderSize(const uint16_t nameSize = 0, const uint16_t extraSize = 0) const;
259     /**
260      * @brief Get entry data offset.
261      * @param zipEntry Indicates the ZipEntry object.
262      * @param extraSize Indicates the extraSize.
263      * @return Returns position.
264      */
265     ZipPos GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const;
266     /**
267      * @brief Check data description.
268      * @param zipEntry Indicates the ZipEntry object.
269      * @param localHeader Indicates the localHeader object.
270      * @return Returns true if successfully checked; returns false otherwise.
271      */
272     bool CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const;
273     /**
274      * @brief Check coherency LocalHeader object.
275      * @param zipEntry Indicates the ZipEntry object.
276      * @param extraSize Indicates the obtained size.
277      * @return Returns true if successfully checked; returns false otherwise.
278      */
279     bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const;
280     /**
281      * @brief Unzip ZipEntry object to ostream.
282      * @param zipEntry Indicates the ZipEntry object.
283      * @param extraSize Indicates the size.
284      * @param dest Indicates the obtained ostream object.
285      * @return Returns true if successfully Unzip; returns false otherwise.
286      */
287     bool UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const;
288     /**
289      * @brief Unzip ZipEntry object to ostream.
290      * @param zipEntry Indicates the ZipEntry object.
291      * @param extraSize Indicates the size.
292      * @param dest Indicates the obtained ostream object.
293      * @return Returns true if successfully Unzip; returns false otherwise.
294      */
295     bool UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const;
296     /**
297      * @brief Get Entry start.
298      * @param zipEntry Indicates the ZipEntry object.
299      * @param extraSize Indicates the extra size.
300      * @return Returns true if successfully Seeked; returns false otherwise.
301      */
302     size_t GetEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const;
303     /**
304      * @brief Init zlib stream.
305      * @param zstream Indicates the obtained z_stream object.
306      * @return Returns true if successfully init; returns false otherwise.
307      */
308     bool InitZStream(z_stream &zstream) const;
309     /**
310      * @brief Read zlib stream.
311      * @param buffer Indicates the buffer to read.
312      * @param zstream Indicates the obtained z_stream object.
313      * @param remainCompressedSize Indicates the obtained size.
314      * @return Returns true if successfully read; returns false otherwise.
315      */
316     bool ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize, size_t &startPos) const;
317 
318     bool UnzipWithInflatedFromMMap(const ZipEntry &zipEntry, const uint16_t extraSize,
319         void *mmapDataPtr, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const;
320 
321     bool ReadZStreamFromMMap(const BytePtr &buffer, void* &dataPtr,
322         z_stream &zstream, uint32_t &remainCompressedSize) const;
323 
324 private:
325     std::string pathName_;
326     std::shared_ptr<ZipFileReader> zipFileReader_;
327     EndDir endDir_;
328     ZipEntryMap entriesMap_;
329     std::shared_ptr<DirTreeNode> dirRoot_;
330     // offset of central directory relative to zip file.
331     ZipPos centralDirPos_ = 0;
332     // this zip content start offset relative to zip file.
333     ZipPos fileStartPos_ = 0;
334     // this zip content length in the zip file.
335     ZipPos fileLength_ = 0;
336     bool isOpen_ = false;
337 };
338 }  // namespace AbilityBase
339 }  // namespace OHOS
340 #endif  // OHOS_ABILITY_BASE_ZIP_FILE_H
341