1 /* 2 * Copyright (c) 2020 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_BUNDLE_ZIP_FILE_H 17 #define OHOS_BUNDLE_ZIP_FILE_H 18 19 #include <map> 20 #include <string> 21 #include <vector> 22 23 #include "stdint.h" 24 #include "unzip.h" 25 26 namespace OHOS { 27 using ZipPos = ZPOS64_T; 28 using CentralDirEntry = struct CentralDirEntry; 29 using LocalHeader = struct LocalHeader; 30 using EndDir = struct EndDir; 31 using DataDesc = struct DataDesc; 32 using ZipEntry = struct ZipEntry; 33 using ZipEntryMap = std::map<std::string, ZipEntry>; 34 using BytePtr = Byte *; 35 36 // Local file header: descript in APPNOTE-6.3.4 37 // local file header signature 4 bytes (0x04034b50) 38 // version needed to extract 2 bytes 39 // general purpose bit flag 2 bytes 40 // compression method 2 bytes 10 41 // last mod file time 2 bytes 42 // last mod file date 2 bytes 43 // crc-32 4 bytes 44 // compressed size 4 bytes 22 45 // uncompressed size 4 bytes 46 // file name length 2 bytes 47 // extra field length 2 bytes 30 48 struct __attribute__((packed)) LocalHeader { 49 uint32_t signature = 0; 50 uint16_t versionNeeded = 0; 51 uint16_t flags = 0; 52 uint16_t compressionMethod = 0; 53 uint16_t modifiedTime = 0; 54 uint16_t modifiedDate = 0; 55 uint32_t crc = 0; 56 uint32_t compressedSize = 0; 57 uint32_t uncompressedSize = 0; 58 uint16_t nameSize = 0; 59 uint16_t extraSize = 0; 60 }; 61 62 // central file header 63 // Central File header: 64 // central file header signature 4 bytes (0x02014b50) 65 // version made by 2 bytes 66 // version needed to extract 2 bytes 67 // general purpose bit flag 2 bytes 10 68 // compression method 2 bytes 69 // last mod file time 2 bytes 70 // last mod file date 2 bytes 71 // crc-32 4 bytes 20 72 // compressed size 4 bytes 73 // uncompressed size 4 bytes 74 // file name length 2 bytes 30 75 // extra field length 2 bytes 76 // file comment length 2 bytes 77 // disk number start 2 bytes 78 // internal file attributes 2 bytes 79 // external file attributes 4 bytes 80 // relative offset of local header 4 bytes 46byte 81 struct __attribute__((packed)) CentralDirEntry { 82 uint32_t signature = 0; 83 uint16_t versionMade = 0; 84 uint16_t versionNeeded = 0; 85 uint16_t flags = 0; // general purpose bit flag 86 uint16_t compressionMethod = 0; 87 uint16_t modifiedTime = 0; 88 uint16_t modifiedDate = 0; 89 uint32_t crc = 0; 90 uint32_t compressedSize = 0; 91 uint32_t uncompressedSize = 0; 92 uint16_t nameSize = 0; 93 uint16_t extraSize = 0; 94 uint16_t commentSize = 0; 95 uint16_t diskNumStart = 0; 96 uint16_t internalAttr = 0; 97 uint32_t externalAttr = 0; 98 uint32_t localHeaderOffset = 0; 99 }; 100 101 struct __attribute__((packed)) EndDir { 102 uint32_t signature = 0; 103 uint16_t numDisk = 0; 104 uint16_t startDiskOfCentralDir = 0; 105 uint16_t totalEntriesInThisDisk = 0; 106 uint16_t totalEntries = 0; 107 uint32_t sizeOfCentralDir = 0; 108 uint32_t offset = 0; 109 uint16_t commentLen = 0; 110 }; 111 112 // Data descriptor: 113 // data descriptor signature 4 bytes (0x06054b50) 114 // crc-32 4 bytes 115 // compressed size 4 bytes 116 // uncompressed size 4 bytes 117 // This descriptor MUST exist if bit 3 of the general purpose bit flag is set (see below). 118 // It is byte aligned and immediately follows the last byte of compressed data. 119 struct __attribute__((packed)) DataDesc { 120 uint32_t signature = 0; 121 uint32_t crc = 0; 122 uint32_t compressedSize = 0; 123 uint32_t uncompressedSize = 0; 124 }; 125 126 struct ZipEntry { 127 ZipEntry() = default; 128 explicit ZipEntry(const CentralDirEntry ¢ralEntry); 129 ~ZipEntry() = default; 130 131 uint16_t compressionMethod = 0; 132 uint32_t uncompressedSize = 0; 133 uint32_t compressedSize = 0; 134 uint32_t localHeaderOffset = 0; 135 uint32_t crc = 0; 136 uint16_t flags = 0; 137 std::string fileName; 138 }; 139 140 // zip file extract class for bundle format. 141 class ZipFile { 142 public: 143 explicit ZipFile(const std::string &pathName); 144 ~ZipFile(); 145 146 bool Open(); 147 void Close(); 148 // set this zip content start offset and length in the zip file form pathName. 149 void SetContentLocation(ZipPos start, size_t length); 150 151 const ZipEntryMap &GetAllEntries() const; 152 bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const; 153 bool ExtractFile(const std::string &file, std::ostream &dest) const; 154 const std::vector<std::string> &GetFileNames() const; 155 156 private: 157 bool CheckEndDir(const EndDir &endDir) const; 158 bool ParseEndDirectory(); 159 bool ParseAllEntries(); 160 size_t GetLocalHeaderSize(const uint16_t nameSize = 0, const uint16_t extraSize = 0) const; 161 bool CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const; 162 bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const; 163 bool UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const; 164 bool UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const; 165 bool SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const; 166 bool InitZStream(z_stream &zstream) const; 167 bool ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize) const; 168 169 private: 170 std::string pathName_; 171 FILE* file_ = nullptr; 172 EndDir endDir_; 173 ZipEntryMap entriesMap_; 174 // offset of central directory relative to zip file. 175 ZipPos centralDirPos_ = 0; 176 // this zip content length in the zip file. 177 ZipPos fileLength_ = 0; 178 // entryName vector 179 std::vector<std::string> fileNames_; 180 bool isOpen_ = false; 181 }; 182 } // namespace OHOS 183 #endif // OHOS_BUNDLE_ZIP_FILE_H