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