1 /* 2 * Copyright (c) 2021 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 FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H 17 #define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H 18 19 #include <cstdint> 20 #include <map> 21 #include <string> 22 23 #include "unzip.h" 24 25 namespace OHOS { 26 namespace AppExecFwk { 27 28 using ZipPos = ZPOS64_T; 29 using CentralDirEntry = struct CentralDirEntry; 30 using LocalHeader = struct LocalHeader; 31 using EndDir = struct EndDir; 32 using DataDesc = struct DataDesc; 33 using ZipEntry = struct ZipEntry; 34 using ZipEntryMap = std::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 ¢ralEntry); 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 std::string fileName; 153 }; 154 155 // zip file extract class for bundle format. 156 class ZipFile { 157 public: 158 explicit ZipFile(const std::string &pathName); 159 ~ZipFile(); 160 /** 161 * @brief Open zip file. 162 * @return Returns true if the zip file is successfully opened; returns false otherwise. 163 */ 164 bool Open(); 165 /** 166 * @brief Close zip file. 167 */ 168 void Close(); 169 /** 170 * @brief Set this zip content start offset and length in the zip file form pathName. 171 * @param start Indicates the zip content location start position. 172 * @param length Indicates the zip content length. 173 */ 174 void SetContentLocation(ZipPos start, size_t length); 175 /** 176 * @brief Get all entries in the zip file. 177 * @param start Indicates the zip content location start position. 178 * @param length Indicates the zip content length. 179 * @return Returns the ZipEntryMap object cotain all entries. 180 */ 181 const ZipEntryMap &GetAllEntries() const; 182 /** 183 * @brief Get entry by name. 184 * @param entryName Indicates the entry name. 185 * @param resultEntry Indicates the obtained ZipEntry object. 186 * @return Returns true if the ZipEntry is successfully finded; returns false otherwise. 187 */ 188 bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const; 189 /** 190 * @brief Get data relative offset for file. 191 * @param file Indicates the entry name. 192 * @param offset Indicates the obtained offset. 193 * @param length Indicates the length. 194 * @return Returns true if this function is successfully called; returns false otherwise. 195 */ 196 bool GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const; 197 /** 198 * @brief Get data relative offset for file. 199 * @param file Indicates the entry name. 200 * @param dest Indicates the obtained ostream object. 201 * @return Returns true if file is successfully extracted; returns false otherwise. 202 */ 203 bool ExtractFile(const std::string &file, std::ostream &dest) const; 204 205 private: 206 /** 207 * @brief Check the EndDir object. 208 * @param endDir Indicates the EndDir object to check. 209 * @return Returns true if successfully checked; returns false otherwise. 210 */ 211 bool CheckEndDir(const EndDir &endDir) const; 212 /** 213 * @brief Parse the EndDir. 214 * @return Returns true if successfully Parsed; returns false otherwise. 215 */ 216 bool ParseEndDirectory(); 217 /** 218 * @brief Parse all Entries. 219 * @return Returns true if successfully parsed; returns false otherwise. 220 */ 221 bool ParseAllEntries(); 222 /** 223 * @brief Get LocalHeader object size. 224 * @param nameSize Indicates the nameSize. 225 * @param extraSize Indicates the extraSize. 226 * @return Returns size of LocalHeader. 227 */ 228 size_t GetLocalHeaderSize(const uint16_t nameSize = 0, const uint16_t extraSize = 0) const; 229 /** 230 * @brief Get entry data offset. 231 * @param zipEntry Indicates the ZipEntry object. 232 * @param extraSize Indicates the extraSize. 233 * @return Returns position. 234 */ 235 ZipPos GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const; 236 /** 237 * @brief Check data description. 238 * @param zipEntry Indicates the ZipEntry object. 239 * @param localHeader Indicates the localHeader object. 240 * @return Returns true if successfully checked; returns false otherwise. 241 */ 242 bool CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const; 243 /** 244 * @brief Check coherency LocalHeader object. 245 * @param zipEntry Indicates the ZipEntry object. 246 * @param extraSize Indicates the obtained size. 247 * @return Returns true if successfully checked; returns false otherwise. 248 */ 249 bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const; 250 /** 251 * @brief Unzip ZipEntry object to ostream. 252 * @param zipEntry Indicates the ZipEntry object. 253 * @param extraSize Indicates the size. 254 * @param dest Indicates the obtained ostream object. 255 * @return Returns true if successfully Unzip; returns false otherwise. 256 */ 257 bool UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const; 258 /** 259 * @brief Unzip ZipEntry object to ostream. 260 * @param zipEntry Indicates the ZipEntry object. 261 * @param extraSize Indicates the size. 262 * @param dest Indicates the obtained ostream object. 263 * @return Returns true if successfully Unzip; returns false otherwise. 264 */ 265 bool UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const; 266 /** 267 * @brief Seek to Entry start. 268 * @param zipEntry Indicates the ZipEntry object. 269 * @param extraSize Indicates the extra size. 270 * @return Returns true if successfully Seeked; returns false otherwise. 271 */ 272 bool SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const; 273 /** 274 * @brief Init zlib stream. 275 * @param zstream Indicates the obtained z_stream object. 276 * @return Returns true if successfully init; returns false otherwise. 277 */ 278 bool InitZStream(z_stream &zstream) const; 279 /** 280 * @brief Read zlib stream. 281 * @param buffer Indicates the buffer to read. 282 * @param zstream Indicates the obtained z_stream object. 283 * @param remainCompressedSize Indicates the obtained size. 284 * @return Returns true if successfully read; returns false otherwise. 285 */ 286 bool ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize) const; 287 288 private: 289 std::string pathName_; 290 FILE *file_ = nullptr; 291 EndDir endDir_; 292 ZipEntryMap entriesMap_; 293 // offset of central directory relative to zip file. 294 ZipPos centralDirPos_ = 0; 295 // this zip content start offset relative to zip file. 296 ZipPos fileStartPos_ = 0; 297 // this zip content length in the zip file. 298 ZipPos fileLength_ = 0; 299 bool isOpen_ = false; 300 }; 301 302 } // namespace AppExecFwk 303 } // namespace OHOS 304 #endif // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H 305