1600cc4afSopenharmony_ci/*
2600cc4afSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3600cc4afSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4600cc4afSopenharmony_ci * you may not use this file except in compliance with the License.
5600cc4afSopenharmony_ci * You may obtain a copy of the License at
6600cc4afSopenharmony_ci *
7600cc4afSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8600cc4afSopenharmony_ci *
9600cc4afSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10600cc4afSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11600cc4afSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12600cc4afSopenharmony_ci * See the License for the specific language governing permissions and
13600cc4afSopenharmony_ci * limitations under the License.
14600cc4afSopenharmony_ci */
15600cc4afSopenharmony_ci
16600cc4afSopenharmony_ci#ifndef FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
17600cc4afSopenharmony_ci#define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
18600cc4afSopenharmony_ci
19600cc4afSopenharmony_ci#include <cstdint>
20600cc4afSopenharmony_ci#include <map>
21600cc4afSopenharmony_ci#include <string>
22600cc4afSopenharmony_ci
23600cc4afSopenharmony_ci#include "unzip.h"
24600cc4afSopenharmony_ci
25600cc4afSopenharmony_cinamespace OHOS {
26600cc4afSopenharmony_cinamespace AppExecFwk {
27600cc4afSopenharmony_cistruct CentralDirEntry;
28600cc4afSopenharmony_cistruct ZipEntry;
29600cc4afSopenharmony_ciusing ZipPos = ZPOS64_T;
30600cc4afSopenharmony_ciusing ZipEntryMap = std::map<std::string, ZipEntry>;
31600cc4afSopenharmony_ciusing BytePtr = Byte *;
32600cc4afSopenharmony_ci
33600cc4afSopenharmony_ci// Local file header: descript in APPNOTE-6.3.4
34600cc4afSopenharmony_ci//    local file header signature     4 bytes  (0x04034b50)
35600cc4afSopenharmony_ci//    version needed to extract       2 bytes
36600cc4afSopenharmony_ci//    general purpose bit flag        2 bytes
37600cc4afSopenharmony_ci//    compression method              2 bytes  10
38600cc4afSopenharmony_ci//    last mod file time              2 bytes
39600cc4afSopenharmony_ci//    last mod file date              2 bytes
40600cc4afSopenharmony_ci//    crc-32                          4 bytes
41600cc4afSopenharmony_ci//    compressed size                 4 bytes  22
42600cc4afSopenharmony_ci//    uncompressed size               4 bytes
43600cc4afSopenharmony_ci//    file name length                2 bytes
44600cc4afSopenharmony_ci//    extra field length              2 bytes  30
45600cc4afSopenharmony_cistruct __attribute__((packed)) LocalHeader {
46600cc4afSopenharmony_ci    uint32_t signature = 0;
47600cc4afSopenharmony_ci    uint16_t versionNeeded = 0;
48600cc4afSopenharmony_ci    uint16_t flags = 0;
49600cc4afSopenharmony_ci    uint16_t compressionMethod = 0;
50600cc4afSopenharmony_ci    uint16_t modifiedTime = 0;
51600cc4afSopenharmony_ci    uint16_t modifiedDate = 0;
52600cc4afSopenharmony_ci    uint32_t crc = 0;
53600cc4afSopenharmony_ci    uint32_t compressedSize = 0;
54600cc4afSopenharmony_ci    uint32_t uncompressedSize = 0;
55600cc4afSopenharmony_ci    uint16_t nameSize = 0;
56600cc4afSopenharmony_ci    uint16_t extraSize = 0;
57600cc4afSopenharmony_ci};
58600cc4afSopenharmony_ci
59600cc4afSopenharmony_ci// central file header
60600cc4afSopenharmony_ci//    Central File header:
61600cc4afSopenharmony_ci//    central file header signature   4 bytes  (0x02014b50)
62600cc4afSopenharmony_ci//    version made by                 2 bytes
63600cc4afSopenharmony_ci//    version needed to extract       2 bytes
64600cc4afSopenharmony_ci//    general purpose bit flag        2 bytes  10
65600cc4afSopenharmony_ci//    compression method              2 bytes
66600cc4afSopenharmony_ci//    last mod file time              2 bytes
67600cc4afSopenharmony_ci//    last mod file date              2 bytes
68600cc4afSopenharmony_ci//    crc-32                          4 bytes  20
69600cc4afSopenharmony_ci//    compressed size                 4 bytes
70600cc4afSopenharmony_ci//    uncompressed size               4 bytes
71600cc4afSopenharmony_ci//    file name length                2 bytes  30
72600cc4afSopenharmony_ci//    extra field length              2 bytes
73600cc4afSopenharmony_ci//    file comment length             2 bytes
74600cc4afSopenharmony_ci//    disk number start               2 bytes
75600cc4afSopenharmony_ci//    internal file attributes        2 bytes
76600cc4afSopenharmony_ci//    external file attributes        4 bytes
77600cc4afSopenharmony_ci//    relative offset of local header 4 bytes 46byte
78600cc4afSopenharmony_cistruct __attribute__((packed)) CentralDirEntry {
79600cc4afSopenharmony_ci    uint32_t signature = 0;
80600cc4afSopenharmony_ci    uint16_t versionMade = 0;
81600cc4afSopenharmony_ci    uint16_t versionNeeded = 0;
82600cc4afSopenharmony_ci    uint16_t flags = 0;  // general purpose bit flag
83600cc4afSopenharmony_ci    uint16_t compressionMethod = 0;
84600cc4afSopenharmony_ci    uint16_t modifiedTime = 0;
85600cc4afSopenharmony_ci    uint16_t modifiedDate = 0;
86600cc4afSopenharmony_ci    uint32_t crc = 0;
87600cc4afSopenharmony_ci    uint32_t compressedSize = 0;
88600cc4afSopenharmony_ci    uint32_t uncompressedSize = 0;
89600cc4afSopenharmony_ci    uint16_t nameSize = 0;
90600cc4afSopenharmony_ci    uint16_t extraSize = 0;
91600cc4afSopenharmony_ci    uint16_t commentSize = 0;
92600cc4afSopenharmony_ci    uint16_t diskNumStart = 0;
93600cc4afSopenharmony_ci    uint16_t internalAttr = 0;
94600cc4afSopenharmony_ci    uint32_t externalAttr = 0;
95600cc4afSopenharmony_ci    uint32_t localHeaderOffset = 0;
96600cc4afSopenharmony_ci};
97600cc4afSopenharmony_ci
98600cc4afSopenharmony_ci// end of central directory packed structure
99600cc4afSopenharmony_ci//    end of central dir signature    4 bytes  (0x06054b50)
100600cc4afSopenharmony_ci//    number of this disk             2 bytes
101600cc4afSopenharmony_ci//    number of the disk with the
102600cc4afSopenharmony_ci//    start of the central directory  2 bytes
103600cc4afSopenharmony_ci//    total number of entries in the
104600cc4afSopenharmony_ci//    central directory on this disk  2 bytes
105600cc4afSopenharmony_ci//    total number of entries in
106600cc4afSopenharmony_ci//    the central directory           2 bytes
107600cc4afSopenharmony_ci//    size of the central directory   4 bytes
108600cc4afSopenharmony_ci//    offset of start of central
109600cc4afSopenharmony_ci//    directory with respect to
110600cc4afSopenharmony_ci//    the starting disk number        4 bytes
111600cc4afSopenharmony_ci//    .ZIP file comment length        2 bytes
112600cc4afSopenharmony_cistruct __attribute__((packed)) EndDir {
113600cc4afSopenharmony_ci    uint32_t signature = 0;
114600cc4afSopenharmony_ci    uint16_t numDisk = 0;
115600cc4afSopenharmony_ci    uint16_t startDiskOfCentralDir = 0;
116600cc4afSopenharmony_ci    uint16_t totalEntriesInThisDisk = 0;
117600cc4afSopenharmony_ci    uint16_t totalEntries = 0;
118600cc4afSopenharmony_ci    uint32_t sizeOfCentralDir = 0;
119600cc4afSopenharmony_ci    uint32_t offset = 0;
120600cc4afSopenharmony_ci    uint16_t commentLen = 0;
121600cc4afSopenharmony_ci};
122600cc4afSopenharmony_ci
123600cc4afSopenharmony_ci// Data descriptor:
124600cc4afSopenharmony_ci//    data descriptor signature       4 bytes  (0x06054b50)
125600cc4afSopenharmony_ci//    crc-32                          4 bytes
126600cc4afSopenharmony_ci//    compressed size                 4 bytes
127600cc4afSopenharmony_ci//    uncompressed size               4 bytes
128600cc4afSopenharmony_ci// This descriptor MUST exist if bit 3 of the general purpose bit flag is set (see below).
129600cc4afSopenharmony_ci// It is byte aligned and immediately follows the last byte of compressed data.
130600cc4afSopenharmony_cistruct __attribute__((packed)) DataDesc {
131600cc4afSopenharmony_ci    uint32_t signature = 0;
132600cc4afSopenharmony_ci    uint32_t crc = 0;
133600cc4afSopenharmony_ci    uint32_t compressedSize = 0;
134600cc4afSopenharmony_ci    uint32_t uncompressedSize = 0;
135600cc4afSopenharmony_ci};
136600cc4afSopenharmony_ci
137600cc4afSopenharmony_cistruct ZipEntry {
138600cc4afSopenharmony_ci    ZipEntry() = default;
139600cc4afSopenharmony_ci    explicit ZipEntry(const CentralDirEntry &centralEntry);
140600cc4afSopenharmony_ci    ~ZipEntry() = default;  // for CodeDEX warning
141600cc4afSopenharmony_ci
142600cc4afSopenharmony_ci    uint16_t compressionMethod = 0;
143600cc4afSopenharmony_ci    uint32_t uncompressedSize = 0;
144600cc4afSopenharmony_ci    uint32_t compressedSize = 0;
145600cc4afSopenharmony_ci    uint32_t localHeaderOffset = 0;
146600cc4afSopenharmony_ci    uint32_t crc = 0;
147600cc4afSopenharmony_ci    uint16_t flags = 0;
148600cc4afSopenharmony_ci    std::string fileName;
149600cc4afSopenharmony_ci};
150600cc4afSopenharmony_ci
151600cc4afSopenharmony_ci// zip file extract class for bundle format.
152600cc4afSopenharmony_ciclass ZipFile {
153600cc4afSopenharmony_cipublic:
154600cc4afSopenharmony_ci    explicit ZipFile(const std::string &pathName);
155600cc4afSopenharmony_ci    ~ZipFile();
156600cc4afSopenharmony_ci    /**
157600cc4afSopenharmony_ci     * @brief Open zip file.
158600cc4afSopenharmony_ci     * @return Returns true if the zip file is successfully opened; returns false otherwise.
159600cc4afSopenharmony_ci     */
160600cc4afSopenharmony_ci    bool Open();
161600cc4afSopenharmony_ci    /**
162600cc4afSopenharmony_ci     * @brief Close zip file.
163600cc4afSopenharmony_ci     */
164600cc4afSopenharmony_ci    void Close();
165600cc4afSopenharmony_ci    /**
166600cc4afSopenharmony_ci     * @brief Set this zip content start offset and length in the zip file form pathName.
167600cc4afSopenharmony_ci     * @param start Indicates the zip content location start position.
168600cc4afSopenharmony_ci     * @param length Indicates the zip content length.
169600cc4afSopenharmony_ci     */
170600cc4afSopenharmony_ci    void SetContentLocation(ZipPos start, size_t length);
171600cc4afSopenharmony_ci    /**
172600cc4afSopenharmony_ci     * @brief Get all entries in the zip file.
173600cc4afSopenharmony_ci     * @param start Indicates the zip content location start position.
174600cc4afSopenharmony_ci     * @param length Indicates the zip content length.
175600cc4afSopenharmony_ci     * @return Returns the ZipEntryMap object cotain all entries.
176600cc4afSopenharmony_ci     */
177600cc4afSopenharmony_ci    const ZipEntryMap &GetAllEntries() const;
178600cc4afSopenharmony_ci    /**
179600cc4afSopenharmony_ci     * @brief Has entry by name.
180600cc4afSopenharmony_ci     * @param entryName Indicates the entry name.
181600cc4afSopenharmony_ci     * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
182600cc4afSopenharmony_ci     */
183600cc4afSopenharmony_ci    bool HasEntry(const std::string &entryName) const;
184600cc4afSopenharmony_ci
185600cc4afSopenharmony_ci    bool IsDirExist(const std::string &dir) const;
186600cc4afSopenharmony_ci
187600cc4afSopenharmony_ci    /**
188600cc4afSopenharmony_ci     * @brief Get entry by name.
189600cc4afSopenharmony_ci     * @param entryName Indicates the entry name.
190600cc4afSopenharmony_ci     * @param resultEntry Indicates the obtained ZipEntry object.
191600cc4afSopenharmony_ci     * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
192600cc4afSopenharmony_ci     */
193600cc4afSopenharmony_ci    bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const;
194600cc4afSopenharmony_ci    /**
195600cc4afSopenharmony_ci     * @brief Get data relative offset for file.
196600cc4afSopenharmony_ci     * @param file Indicates the entry name.
197600cc4afSopenharmony_ci     * @param offset Indicates the obtained offset.
198600cc4afSopenharmony_ci     * @param length Indicates the length.
199600cc4afSopenharmony_ci     * @return Returns true if this function is successfully called; returns false otherwise.
200600cc4afSopenharmony_ci     */
201600cc4afSopenharmony_ci    bool GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const;
202600cc4afSopenharmony_ci    /**
203600cc4afSopenharmony_ci     * @brief Get data relative offset for file.
204600cc4afSopenharmony_ci     * @param file Indicates the entry name.
205600cc4afSopenharmony_ci     * @param dest Indicates the obtained ostream object.
206600cc4afSopenharmony_ci     * @return Returns true if file is successfully extracted; returns false otherwise.
207600cc4afSopenharmony_ci     */
208600cc4afSopenharmony_ci    bool ExtractFile(const std::string &file, std::ostream &dest) const;
209600cc4afSopenharmony_ci
210600cc4afSopenharmony_ciprivate:
211600cc4afSopenharmony_ci    /**
212600cc4afSopenharmony_ci     * @brief Check the EndDir object.
213600cc4afSopenharmony_ci     * @param endDir Indicates the EndDir object to check.
214600cc4afSopenharmony_ci     * @return Returns true if  successfully checked; returns false otherwise.
215600cc4afSopenharmony_ci     */
216600cc4afSopenharmony_ci    bool CheckEndDir(const EndDir &endDir) const;
217600cc4afSopenharmony_ci    /**
218600cc4afSopenharmony_ci     * @brief Parse the EndDir.
219600cc4afSopenharmony_ci     * @return Returns true if  successfully Parsed; returns false otherwise.
220600cc4afSopenharmony_ci     */
221600cc4afSopenharmony_ci    bool ParseEndDirectory();
222600cc4afSopenharmony_ci    /**
223600cc4afSopenharmony_ci     * @brief Parse all Entries.
224600cc4afSopenharmony_ci     * @return Returns true if successfully parsed; returns false otherwise.
225600cc4afSopenharmony_ci     */
226600cc4afSopenharmony_ci    bool ParseAllEntries();
227600cc4afSopenharmony_ci    /**
228600cc4afSopenharmony_ci     * @brief Get LocalHeader object size.
229600cc4afSopenharmony_ci     * @param nameSize Indicates the nameSize.
230600cc4afSopenharmony_ci     * @param extraSize Indicates the extraSize.
231600cc4afSopenharmony_ci     * @return Returns size of LocalHeader.
232600cc4afSopenharmony_ci     */
233600cc4afSopenharmony_ci    size_t GetLocalHeaderSize(const uint16_t nameSize = 0, const uint16_t extraSize = 0) const;
234600cc4afSopenharmony_ci    /**
235600cc4afSopenharmony_ci     * @brief Get entry data offset.
236600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
237600cc4afSopenharmony_ci     * @param extraSize Indicates the extraSize.
238600cc4afSopenharmony_ci     * @return Returns position.
239600cc4afSopenharmony_ci     */
240600cc4afSopenharmony_ci    ZipPos GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const;
241600cc4afSopenharmony_ci    /**
242600cc4afSopenharmony_ci     * @brief Check data description.
243600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
244600cc4afSopenharmony_ci     * @param localHeader Indicates the localHeader object.
245600cc4afSopenharmony_ci     * @return Returns true if successfully checked; returns false otherwise.
246600cc4afSopenharmony_ci     */
247600cc4afSopenharmony_ci    bool CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const;
248600cc4afSopenharmony_ci    /**
249600cc4afSopenharmony_ci     * @brief Check coherency LocalHeader object.
250600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
251600cc4afSopenharmony_ci     * @param extraSize Indicates the obtained size.
252600cc4afSopenharmony_ci     * @return Returns true if successfully checked; returns false otherwise.
253600cc4afSopenharmony_ci     */
254600cc4afSopenharmony_ci    bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const;
255600cc4afSopenharmony_ci    /**
256600cc4afSopenharmony_ci     * @brief Unzip ZipEntry object to ostream.
257600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
258600cc4afSopenharmony_ci     * @param extraSize Indicates the size.
259600cc4afSopenharmony_ci     * @param dest Indicates the obtained ostream object.
260600cc4afSopenharmony_ci     * @return Returns true if successfully Unzip; returns false otherwise.
261600cc4afSopenharmony_ci     */
262600cc4afSopenharmony_ci    bool UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const;
263600cc4afSopenharmony_ci    /**
264600cc4afSopenharmony_ci     * @brief Unzip ZipEntry object to ostream.
265600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
266600cc4afSopenharmony_ci     * @param extraSize Indicates the size.
267600cc4afSopenharmony_ci     * @param dest Indicates the obtained ostream object.
268600cc4afSopenharmony_ci     * @return Returns true if successfully Unzip; returns false otherwise.
269600cc4afSopenharmony_ci     */
270600cc4afSopenharmony_ci    bool UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const;
271600cc4afSopenharmony_ci    /**
272600cc4afSopenharmony_ci     * @brief Seek to Entry start.
273600cc4afSopenharmony_ci     * @param zipEntry Indicates the ZipEntry object.
274600cc4afSopenharmony_ci     * @param extraSize Indicates the extra size.
275600cc4afSopenharmony_ci     * @return Returns true if successfully Seeked; returns false otherwise.
276600cc4afSopenharmony_ci     */
277600cc4afSopenharmony_ci    bool SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const;
278600cc4afSopenharmony_ci    /**
279600cc4afSopenharmony_ci     * @brief Init zlib stream.
280600cc4afSopenharmony_ci     * @param zstream Indicates the obtained z_stream object.
281600cc4afSopenharmony_ci     * @return Returns true if successfully init; returns false otherwise.
282600cc4afSopenharmony_ci     */
283600cc4afSopenharmony_ci    bool InitZStream(z_stream &zstream) const;
284600cc4afSopenharmony_ci    /**
285600cc4afSopenharmony_ci     * @brief Read zlib stream.
286600cc4afSopenharmony_ci     * @param buffer Indicates the buffer to read.
287600cc4afSopenharmony_ci     * @param zstream Indicates the obtained z_stream object.
288600cc4afSopenharmony_ci     * @param remainCompressedSize Indicates the obtained size.
289600cc4afSopenharmony_ci     * @return Returns true if successfully read; returns false otherwise.
290600cc4afSopenharmony_ci     */
291600cc4afSopenharmony_ci    bool ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize) const;
292600cc4afSopenharmony_ci
293600cc4afSopenharmony_ciprivate:
294600cc4afSopenharmony_ci    std::string pathName_;
295600cc4afSopenharmony_ci    FILE *file_ = nullptr;
296600cc4afSopenharmony_ci    EndDir endDir_;
297600cc4afSopenharmony_ci    ZipEntryMap entriesMap_;
298600cc4afSopenharmony_ci    // offset of central directory relative to zip file.
299600cc4afSopenharmony_ci    ZipPos centralDirPos_ = 0;
300600cc4afSopenharmony_ci    // this zip content start offset relative to zip file.
301600cc4afSopenharmony_ci    ZipPos fileStartPos_ = 0;
302600cc4afSopenharmony_ci    // this zip content length in the zip file.
303600cc4afSopenharmony_ci    ZipPos fileLength_ = 0;
304600cc4afSopenharmony_ci    bool isOpen_ = false;
305600cc4afSopenharmony_ci};
306600cc4afSopenharmony_ci}  // namespace AppExecFwk
307600cc4afSopenharmony_ci}  // namespace OHOS
308600cc4afSopenharmony_ci#endif  // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
309