1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "pkg_zipfile.h"
16fb299fa2Sopenharmony_ci#include <ctime>
17fb299fa2Sopenharmony_ci#include <limits>
18fb299fa2Sopenharmony_ci#include "dump.h"
19fb299fa2Sopenharmony_ci#include "pkg_algorithm.h"
20fb299fa2Sopenharmony_ci#include "pkg_manager.h"
21fb299fa2Sopenharmony_ci#include "pkg_stream.h"
22fb299fa2Sopenharmony_ci#include "zip_pkg_parse.h"
23fb299fa2Sopenharmony_ci#include "zlib.h"
24fb299fa2Sopenharmony_ci
25fb299fa2Sopenharmony_cinamespace Hpackage {
26fb299fa2Sopenharmony_ciconstexpr uint32_t TM_YEAR_BITS = 9;
27fb299fa2Sopenharmony_ciconstexpr uint32_t TM_MON_BITS = 5;
28fb299fa2Sopenharmony_ciconstexpr uint32_t TM_MIN_BITS = 5;
29fb299fa2Sopenharmony_ciconstexpr uint32_t TM_HOUR_BITS = 11;
30fb299fa2Sopenharmony_ciconstexpr uint32_t BIG_SIZE_HEADER = 20;
31fb299fa2Sopenharmony_ciconstexpr uint32_t START_YEAR = 1900;
32fb299fa2Sopenharmony_ciconstexpr uint32_t MAX_FILE_NAME = 256;
33fb299fa2Sopenharmony_ciconstexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50;
34fb299fa2Sopenharmony_ciconstexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50;
35fb299fa2Sopenharmony_ciconstexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50;
36fb299fa2Sopenharmony_ciconstexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50;
37fb299fa2Sopenharmony_ciconstexpr uint32_t MAX_BUFFER_SIZE = 1024 * 64;
38fb299fa2Sopenharmony_ci// mask value that signifies that the entry has a DD
39fb299fa2Sopenharmony_ciconstexpr uint32_t GPBDD_FLAG_MASK = 0x0008;
40fb299fa2Sopenharmony_ciconstexpr uint32_t ZIP_PKG_ALIGNMENT_DEF = 1;
41fb299fa2Sopenharmony_ciconstexpr int32_t DEF_MEM_LEVEL = 8;
42fb299fa2Sopenharmony_ciconstexpr int32_t Z_STORED = 0;
43fb299fa2Sopenharmony_ci
44fb299fa2Sopenharmony_ciint32_t ZipPkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream)
45fb299fa2Sopenharmony_ci{
46fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING)) {
47fb299fa2Sopenharmony_ci        PKG_LOGE("Error state curr %d ", state_);
48fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
49fb299fa2Sopenharmony_ci    }
50fb299fa2Sopenharmony_ci    if (file == nullptr || inStream == nullptr) {
51fb299fa2Sopenharmony_ci        PKG_LOGE("AddEntry failed, invalid param");
52fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
53fb299fa2Sopenharmony_ci    }
54fb299fa2Sopenharmony_ci    PKG_LOGI("ZipPkgFile::AddEntry %s ", file->identity.c_str());
55fb299fa2Sopenharmony_ci
56fb299fa2Sopenharmony_ci    int32_t ret = PKG_SUCCESS;
57fb299fa2Sopenharmony_ci    ZipFileEntry* entry = (ZipFileEntry*)AddPkgEntry(file->identity);
58fb299fa2Sopenharmony_ci    if (entry == nullptr) {
59fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to create pkg node for %s", file->identity.c_str());
60fb299fa2Sopenharmony_ci        return PKG_NONE_MEMORY;
61fb299fa2Sopenharmony_ci    }
62fb299fa2Sopenharmony_ci    entry->Init(file, inStream);
63fb299fa2Sopenharmony_ci
64fb299fa2Sopenharmony_ci    size_t encodeLen = 0;
65fb299fa2Sopenharmony_ci    ret = entry->EncodeHeader(inStream, currentOffset_, encodeLen);
66fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
67fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to encode for %s", file->identity.c_str());
68fb299fa2Sopenharmony_ci        return ret;
69fb299fa2Sopenharmony_ci    }
70fb299fa2Sopenharmony_ci    currentOffset_ += encodeLen;
71fb299fa2Sopenharmony_ci    ret = entry->Pack(inStream, currentOffset_, encodeLen);
72fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
73fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to pack for %s", file->identity.c_str());
74fb299fa2Sopenharmony_ci        return ret;
75fb299fa2Sopenharmony_ci    }
76fb299fa2Sopenharmony_ci    currentOffset_ += encodeLen;
77fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
78fb299fa2Sopenharmony_ci}
79fb299fa2Sopenharmony_ci
80fb299fa2Sopenharmony_ciint32_t ZipPkgFile::SavePackage(size_t &signOffset)
81fb299fa2Sopenharmony_ci{
82fb299fa2Sopenharmony_ci    UNUSED(signOffset);
83fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE)) {
84fb299fa2Sopenharmony_ci        PKG_LOGE("error state curr %d ", state_);
85fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
86fb299fa2Sopenharmony_ci    }
87fb299fa2Sopenharmony_ci    int32_t ret = PKG_SUCCESS;
88fb299fa2Sopenharmony_ci    size_t offset = currentOffset_;
89fb299fa2Sopenharmony_ci    for (auto &it : pkgEntryMapId_) {
90fb299fa2Sopenharmony_ci        ZipFileEntry* entry = (ZipFileEntry*)it.second;
91fb299fa2Sopenharmony_ci        if (entry == nullptr) {
92fb299fa2Sopenharmony_ci            PKG_LOGE("Failed to write CentralDirEntry");
93fb299fa2Sopenharmony_ci            return PKG_INVALID_PARAM;
94fb299fa2Sopenharmony_ci        }
95fb299fa2Sopenharmony_ci        size_t encodeLen = 0;
96fb299fa2Sopenharmony_ci        entry->EncodeCentralDirEntry(pkgStream_, offset, encodeLen);
97fb299fa2Sopenharmony_ci        offset += encodeLen;
98fb299fa2Sopenharmony_ci    }
99fb299fa2Sopenharmony_ci
100fb299fa2Sopenharmony_ci    std::vector<uint8_t> buff(sizeof(EndCentralDir));
101fb299fa2Sopenharmony_ci    WriteLE32(buff.data() + offsetof(EndCentralDir, signature), END_CENTRAL_SIGNATURE);
102fb299fa2Sopenharmony_ci    WriteLE16(buff.data() + offsetof(EndCentralDir, numDisk), 0);
103fb299fa2Sopenharmony_ci    WriteLE16(buff.data() + offsetof(EndCentralDir, startDiskOfCentralDir), 0);
104fb299fa2Sopenharmony_ci    WriteLE16(buff.data() + offsetof(EndCentralDir, totalEntriesInThisDisk), pkgEntryMapId_.size());
105fb299fa2Sopenharmony_ci    WriteLE16(buff.data() + offsetof(EndCentralDir, totalEntries), pkgEntryMapId_.size());
106fb299fa2Sopenharmony_ci    WriteLE32(buff.data() + offsetof(EndCentralDir, sizeOfCentralDir), offset - currentOffset_);
107fb299fa2Sopenharmony_ci    WriteLE32(buff.data() + offsetof(EndCentralDir, offset), currentOffset_);
108fb299fa2Sopenharmony_ci    WriteLE16(buff.data() + offsetof(EndCentralDir, commentLen), 0);
109fb299fa2Sopenharmony_ci    PkgBuffer buffer(buff);
110fb299fa2Sopenharmony_ci    ret = pkgStream_->Write(buffer, sizeof(EndCentralDir), offset);
111fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
112fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to write CentralDirEntry for %s", pkgStream_->GetFileName().c_str());
113fb299fa2Sopenharmony_ci        return ret;
114fb299fa2Sopenharmony_ci    }
115fb299fa2Sopenharmony_ci    currentOffset_ = offset + sizeof(EndCentralDir);
116fb299fa2Sopenharmony_ci    pkgStream_->Flush(currentOffset_);
117fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
118fb299fa2Sopenharmony_ci}
119fb299fa2Sopenharmony_ci
120fb299fa2Sopenharmony_ciint32_t ZipPkgFile::LoadPackage(std::vector<std::string> &fileNames, PkgBuffer &buffer,
121fb299fa2Sopenharmony_ci    uint32_t endDirLen, size_t endDirPos, size_t &readLen)
122fb299fa2Sopenharmony_ci{
123fb299fa2Sopenharmony_ci    size_t fileLen = pkgStream_->GetFileLength();
124fb299fa2Sopenharmony_ci    EndCentralDir endDir;
125fb299fa2Sopenharmony_ci    endDir.signature = ReadLE32(buffer.buffer + offsetof(EndCentralDir, signature));
126fb299fa2Sopenharmony_ci    endDir.numDisk = ReadLE16(buffer.buffer  + offsetof(EndCentralDir, numDisk));
127fb299fa2Sopenharmony_ci    endDir.startDiskOfCentralDir = ReadLE16(buffer.buffer  + offsetof(EndCentralDir, startDiskOfCentralDir));
128fb299fa2Sopenharmony_ci    endDir.totalEntriesInThisDisk = ReadLE16(buffer.buffer  + offsetof(EndCentralDir, totalEntriesInThisDisk));
129fb299fa2Sopenharmony_ci    endDir.totalEntries = ReadLE16(buffer.buffer  + offsetof(EndCentralDir, totalEntries));
130fb299fa2Sopenharmony_ci    endDir.sizeOfCentralDir = ReadLE32(buffer.buffer  + offsetof(EndCentralDir, sizeOfCentralDir));
131fb299fa2Sopenharmony_ci    endDir.offset = ReadLE32(buffer.buffer  + offsetof(EndCentralDir, offset));
132fb299fa2Sopenharmony_ci    endDir.commentLen = ReadLE16(buffer.buffer  + offsetof(EndCentralDir, commentLen));
133fb299fa2Sopenharmony_ci    if ((endDir.numDisk != 0) || (endDir.signature != END_CENTRAL_SIGNATURE) ||
134fb299fa2Sopenharmony_ci        (endDir.startDiskOfCentralDir != 0)
135fb299fa2Sopenharmony_ci#ifndef UPDATER_UT
136fb299fa2Sopenharmony_ci        || (endDir.offset >= fileLen) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) ||
137fb299fa2Sopenharmony_ci        ((endDir.offset + endDir.sizeOfCentralDir + endDirLen) > fileLen)
138fb299fa2Sopenharmony_ci#endif
139fb299fa2Sopenharmony_ci        ) {
140fb299fa2Sopenharmony_ci        PKG_LOGE("end dir format error %s", pkgStream_->GetFileName().c_str());
141fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_PKG_FORMAT);
142fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
143fb299fa2Sopenharmony_ci    }
144fb299fa2Sopenharmony_ci    size_t currentPos = endDir.offset;
145fb299fa2Sopenharmony_ci    if (endDir.offset == UINT_MAX) {
146fb299fa2Sopenharmony_ci        int32_t ret = pkgStream_->Read(buffer, endDirPos - sizeof(Zip64EndCentralDirLocator),
147fb299fa2Sopenharmony_ci            sizeof(Zip64EndCentralDirLocator), readLen);
148fb299fa2Sopenharmony_ci        uint32_t signature = ReadLE32(buffer.buffer + offsetof(Zip64EndCentralDirLocator, signature));
149fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS || signature != 0x07064b50) {
150fb299fa2Sopenharmony_ci            return ParseFileEntries(fileNames, endDir, currentPos, fileLen);
151fb299fa2Sopenharmony_ci        }
152fb299fa2Sopenharmony_ci        currentPos = ReadLE64(buffer.buffer + offsetof(Zip64EndCentralDirLocator, endOfCentralDirectoryRecord));
153fb299fa2Sopenharmony_ci        ret = pkgStream_->Read(buffer, currentPos, sizeof(Zip64EndCentralDirRecord), readLen);
154fb299fa2Sopenharmony_ci        signature = ReadLE32(buffer.buffer + offsetof(Zip64EndCentralDirRecord, signature));
155fb299fa2Sopenharmony_ci        if (ret == PKG_SUCCESS && signature == 0x06064b50) {
156fb299fa2Sopenharmony_ci            currentPos = ReadLE64(buffer.buffer + offsetof(Zip64EndCentralDirRecord, offset));
157fb299fa2Sopenharmony_ci        }
158fb299fa2Sopenharmony_ci    }
159fb299fa2Sopenharmony_ci    return ParseFileEntries(fileNames, endDir, currentPos, fileLen);
160fb299fa2Sopenharmony_ci}
161fb299fa2Sopenharmony_ci
162fb299fa2Sopenharmony_ciint32_t ZipPkgFile::GetFileLength(size_t &fileLen)
163fb299fa2Sopenharmony_ci{
164fb299fa2Sopenharmony_ci    if (!CheckState({PKG_FILE_STATE_IDLE}, PKG_FILE_STATE_WORKING)) {
165fb299fa2Sopenharmony_ci        PKG_LOGE("Error state curr %d ", state_);
166fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
167fb299fa2Sopenharmony_ci    }
168fb299fa2Sopenharmony_ci    // 先从文件尾部获取 EndCentralDir
169fb299fa2Sopenharmony_ci    fileLen = pkgStream_->GetFileLength();
170fb299fa2Sopenharmony_ci    if (fileLen == 0) {
171fb299fa2Sopenharmony_ci        PKG_LOGE("invalid file to load");
172fb299fa2Sopenharmony_ci        return PKG_INVALID_STATE;
173fb299fa2Sopenharmony_ci    }
174fb299fa2Sopenharmony_ci    if (fileLen > SIZE_MAX) {
175fb299fa2Sopenharmony_ci        PKG_LOGE("Invalid file len %zu to load %s", fileLen, pkgStream_->GetFileName().c_str());
176fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
177fb299fa2Sopenharmony_ci    }
178fb299fa2Sopenharmony_ci    if (fileLen < static_cast<size_t>(sizeof(EndCentralDir))) {
179fb299fa2Sopenharmony_ci        PKG_LOGE("Too small to be zip %s", pkgStream_->GetFileName().c_str());
180fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
181fb299fa2Sopenharmony_ci    }
182fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
183fb299fa2Sopenharmony_ci}
184fb299fa2Sopenharmony_ci
185fb299fa2Sopenharmony_ciint32_t ZipPkgFile::LoadPackage(std::vector<std::string>& fileNames, VerifyFunction verifier)
186fb299fa2Sopenharmony_ci{
187fb299fa2Sopenharmony_ci    UNUSED(verifier);
188fb299fa2Sopenharmony_ci    PKG_LOGI("LoadPackage %s :%zu", pkgStream_->GetFileName().c_str(), pkgStream_->GetFileLength());
189fb299fa2Sopenharmony_ci
190fb299fa2Sopenharmony_ci    // 检查最后面是签名信息还是EndCentralDir
191fb299fa2Sopenharmony_ci    size_t fileLen = 0;
192fb299fa2Sopenharmony_ci    int32_t ret = GetFileLength(fileLen);
193fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
194fb299fa2Sopenharmony_ci        PKG_LOGE("GetFileLength FAIL");
195fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(ret);
196fb299fa2Sopenharmony_ci        return ret;
197fb299fa2Sopenharmony_ci    }
198fb299fa2Sopenharmony_ci    size_t buffSize = sizeof(EndCentralDir);
199fb299fa2Sopenharmony_ci    if (buffSize < sizeof(Zip64EndCentralDirRecord)) {
200fb299fa2Sopenharmony_ci        buffSize = sizeof(Zip64EndCentralDirRecord);
201fb299fa2Sopenharmony_ci    }
202fb299fa2Sopenharmony_ci
203fb299fa2Sopenharmony_ci    size_t signatureLen = 0;
204fb299fa2Sopenharmony_ci    uint32_t magic = 0;
205fb299fa2Sopenharmony_ci    uint32_t endDirLen = sizeof(EndCentralDir);
206fb299fa2Sopenharmony_ci    size_t endDirPos = fileLen - endDirLen;
207fb299fa2Sopenharmony_ci    size_t readLen = 0;
208fb299fa2Sopenharmony_ci    PkgBuffer buffer(nullptr, buffSize);
209fb299fa2Sopenharmony_ci    ret = pkgStream_->Read(buffer, endDirPos, sizeof(EndCentralDir), readLen);
210fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
211fb299fa2Sopenharmony_ci        PKG_LOGE("read EOCD struct failed %s", pkgStream_->GetFileName().c_str());
212fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(ret);
213fb299fa2Sopenharmony_ci        return ret;
214fb299fa2Sopenharmony_ci    }
215fb299fa2Sopenharmony_ci    magic = ReadLE32(buffer.buffer);
216fb299fa2Sopenharmony_ci    if (magic != END_CENTRAL_SIGNATURE) { // 按签名处理
217fb299fa2Sopenharmony_ci        ZipPkgParse zipParse;
218fb299fa2Sopenharmony_ci        PkgSignComment pkgSignComment {};
219fb299fa2Sopenharmony_ci        ret = zipParse.ParseZipPkg(pkgStream_, pkgSignComment);
220fb299fa2Sopenharmony_ci        signatureLen = pkgSignComment.signCommentTotalLen;
221fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
222fb299fa2Sopenharmony_ci            PKG_LOGE("Parse zip package signature failed");
223fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(ret);
224fb299fa2Sopenharmony_ci            return ret;
225fb299fa2Sopenharmony_ci        }
226fb299fa2Sopenharmony_ci
227fb299fa2Sopenharmony_ci        endDirPos -= signatureLen;
228fb299fa2Sopenharmony_ci        ret = pkgStream_->Read(buffer, endDirPos, sizeof(EndCentralDir), readLen);
229fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
230fb299fa2Sopenharmony_ci            PKG_LOGE("read EOCD struct failed %s", pkgStream_->GetFileName().c_str());
231fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(ret);
232fb299fa2Sopenharmony_ci            return ret;
233fb299fa2Sopenharmony_ci        }
234fb299fa2Sopenharmony_ci    }
235fb299fa2Sopenharmony_ci
236fb299fa2Sopenharmony_ci    return LoadPackage(fileNames, buffer, endDirLen, endDirPos, readLen);
237fb299fa2Sopenharmony_ci}
238fb299fa2Sopenharmony_ci
239fb299fa2Sopenharmony_ciint32_t ZipPkgFile::ParseFileEntries(std::vector<std::string> &fileNames,
240fb299fa2Sopenharmony_ci    const EndCentralDir &endDir, size_t currentPos, size_t fileLen)
241fb299fa2Sopenharmony_ci{
242fb299fa2Sopenharmony_ci    Updater::UPDATER_INIT_RECORD;
243fb299fa2Sopenharmony_ci    int32_t ret = PKG_SUCCESS;
244fb299fa2Sopenharmony_ci    size_t buffLen = MAX_FILE_NAME + sizeof(LocalFileHeader) + sizeof(DataDescriptor)
245fb299fa2Sopenharmony_ci        + sizeof(CentralDirEntry) + BIG_SIZE_HEADER;
246fb299fa2Sopenharmony_ci    PkgBuffer buffer(buffLen);
247fb299fa2Sopenharmony_ci
248fb299fa2Sopenharmony_ci    for (int32_t i = 0; i < endDir.totalEntries; i++) {
249fb299fa2Sopenharmony_ci        if (fileLen <= currentPos) {
250fb299fa2Sopenharmony_ci            PKG_LOGE("too small to be zip");
251fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(PKG_INVALID_FILE);
252fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
253fb299fa2Sopenharmony_ci        }
254fb299fa2Sopenharmony_ci
255fb299fa2Sopenharmony_ci        ZipFileEntry* entry = new ZipFileEntry(this, nodeId_++);
256fb299fa2Sopenharmony_ci        if (entry == nullptr) {
257fb299fa2Sopenharmony_ci            PKG_LOGE("Failed to create zip node for %s", pkgStream_->GetFileName().c_str());
258fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(PKG_NONE_MEMORY);
259fb299fa2Sopenharmony_ci            return PKG_NONE_MEMORY;
260fb299fa2Sopenharmony_ci        }
261fb299fa2Sopenharmony_ci
262fb299fa2Sopenharmony_ci        // 从文件中解析出文件头信息,保存在entry中
263fb299fa2Sopenharmony_ci        size_t decodeLen = 0;
264fb299fa2Sopenharmony_ci        ret = entry->DecodeHeader(buffer, currentPos, 0, decodeLen);
265fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
266fb299fa2Sopenharmony_ci            PKG_LOGE("DecodeHeader failed");
267fb299fa2Sopenharmony_ci            delete entry;
268fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(ret);
269fb299fa2Sopenharmony_ci            return ret;
270fb299fa2Sopenharmony_ci        }
271fb299fa2Sopenharmony_ci
272fb299fa2Sopenharmony_ci        // 保存entry文件
273fb299fa2Sopenharmony_ci        pkgEntryMapId_.insert(std::pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), (PkgEntryPtr)entry));
274fb299fa2Sopenharmony_ci        pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), (PkgEntryPtr)entry));
275fb299fa2Sopenharmony_ci        fileNames.push_back(entry->GetFileName());
276fb299fa2Sopenharmony_ci
277fb299fa2Sopenharmony_ci        currentPos += decodeLen;
278fb299fa2Sopenharmony_ci    }
279fb299fa2Sopenharmony_ci    return ret;
280fb299fa2Sopenharmony_ci}
281fb299fa2Sopenharmony_ci
282fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
283fb299fa2Sopenharmony_ci{
284fb299fa2Sopenharmony_ci    // 对zip包,数据和数据头信息在连续位置,使用一个打包
285fb299fa2Sopenharmony_ci    encodeLen = 0;
286fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.headerOffset = startOffset;
287fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
288fb299fa2Sopenharmony_ci}
289fb299fa2Sopenharmony_ci
290fb299fa2Sopenharmony_ciint32_t ZipFileEntry::PackStream(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen,
291fb299fa2Sopenharmony_ci    const PkgAlgorithm::PkgAlgorithmPtr algorithm, const PkgStreamPtr outStream)
292fb299fa2Sopenharmony_ci{
293fb299fa2Sopenharmony_ci    // 为header申请一个buff,先处理到内存,后面在写入文件
294fb299fa2Sopenharmony_ci    std::vector<uint8_t> buff(MAX_FILE_NAME + sizeof(LocalFileHeader) + ZIP_PKG_ALIGNMENT_DEF);
295fb299fa2Sopenharmony_ci    size_t nameLen = 0;
296fb299fa2Sopenharmony_ci    PkgFileImpl::ConvertStringToBuffer(fileInfo_.fileInfo.identity, {
297fb299fa2Sopenharmony_ci        buff.data() + sizeof(LocalFileHeader), buff.capacity()
298fb299fa2Sopenharmony_ci    }, nameLen);
299fb299fa2Sopenharmony_ci
300fb299fa2Sopenharmony_ci    size_t headerLen = nameLen + sizeof(LocalFileHeader);
301fb299fa2Sopenharmony_ci    bool hasDataDesc = true;
302fb299fa2Sopenharmony_ci    if (fileInfo_.method == Z_DEFLATED) {
303fb299fa2Sopenharmony_ci#ifndef UPDATER_UT
304fb299fa2Sopenharmony_ci        hasDataDesc = false;
305fb299fa2Sopenharmony_ci#endif
306fb299fa2Sopenharmony_ci    }
307fb299fa2Sopenharmony_ci
308fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.dataOffset = startOffset + headerLen;
309fb299fa2Sopenharmony_ci    PkgAlgorithmContext context = {
310fb299fa2Sopenharmony_ci        {0, startOffset + headerLen},
311fb299fa2Sopenharmony_ci        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
312fb299fa2Sopenharmony_ci        0, fileInfo_.fileInfo.digestMethod
313fb299fa2Sopenharmony_ci    };
314fb299fa2Sopenharmony_ci    int32_t ret = algorithm->Pack(inStream, outStream, context);
315fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
316fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to compress for %s", fileInfo_.fileInfo.identity.c_str());
317fb299fa2Sopenharmony_ci        return ret;
318fb299fa2Sopenharmony_ci    }
319fb299fa2Sopenharmony_ci    // 填充file信息,压缩后的长度和crc
320fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packedSize = context.packedSize;
321fb299fa2Sopenharmony_ci    crc32_ = context.crc;
322fb299fa2Sopenharmony_ci
323fb299fa2Sopenharmony_ci    // 构建文件头信息,从startOffset开始
324fb299fa2Sopenharmony_ci    ret = EncodeLocalFileHeader(buff.data(), sizeof(LocalFileHeader), hasDataDesc, nameLen);
325fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
326fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to encodeFileHeader for %s", fileInfo_.fileInfo.identity.c_str());
327fb299fa2Sopenharmony_ci        return ret;
328fb299fa2Sopenharmony_ci    }
329fb299fa2Sopenharmony_ci    PkgBuffer buffer(buff);
330fb299fa2Sopenharmony_ci    ret = outStream->Write(buffer, headerLen, startOffset);
331fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
332fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to write header for %s", fileInfo_.fileInfo.identity.c_str());
333fb299fa2Sopenharmony_ci        return ret;
334fb299fa2Sopenharmony_ci    }
335fb299fa2Sopenharmony_ci
336fb299fa2Sopenharmony_ci    if (hasDataDesc) { //  数据描述部分
337fb299fa2Sopenharmony_ci        uint32_t encodeDataDescLen = 0;
338fb299fa2Sopenharmony_ci        ret = EncodeDataDescriptor(outStream,
339fb299fa2Sopenharmony_ci            startOffset + headerLen + fileInfo_.fileInfo.packedSize, encodeDataDescLen);
340fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
341fb299fa2Sopenharmony_ci            PKG_LOGE("Failed to encodeDataDescriptor for %s", fileInfo_.fileInfo.identity.c_str());
342fb299fa2Sopenharmony_ci            return ret;
343fb299fa2Sopenharmony_ci        }
344fb299fa2Sopenharmony_ci        headerLen += encodeDataDescLen;
345fb299fa2Sopenharmony_ci    }
346fb299fa2Sopenharmony_ci    encodeLen = headerLen + fileInfo_.fileInfo.packedSize;
347fb299fa2Sopenharmony_ci    PKG_LOGI("Pack packedSize:%zu unpackedSize: %zu offset: %zu %zu", fileInfo_.fileInfo.packedSize,
348fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset);
349fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
350fb299fa2Sopenharmony_ci}
351fb299fa2Sopenharmony_ci
352fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
353fb299fa2Sopenharmony_ci{
354fb299fa2Sopenharmony_ci    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
355fb299fa2Sopenharmony_ci    PkgStreamPtr outStream = pkgFile_->GetPkgStream();
356fb299fa2Sopenharmony_ci    if (fileInfo_.fileInfo.headerOffset != startOffset) {
357fb299fa2Sopenharmony_ci        PKG_LOGE("Offset error %zu %zu %s", fileInfo_.fileInfo.headerOffset,
358fb299fa2Sopenharmony_ci            startOffset, fileInfo_.fileInfo.identity.c_str());
359fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
360fb299fa2Sopenharmony_ci    }
361fb299fa2Sopenharmony_ci    if (algorithm == nullptr || outStream == nullptr || inStream == nullptr) {
362fb299fa2Sopenharmony_ci        PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
363fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
364fb299fa2Sopenharmony_ci    }
365fb299fa2Sopenharmony_ci    return PackStream(inStream, startOffset, encodeLen, algorithm, outStream);
366fb299fa2Sopenharmony_ci}
367fb299fa2Sopenharmony_ci
368fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeCentralDirEntry(const PkgStreamPtr stream, size_t startOffset, size_t &encodeLen)
369fb299fa2Sopenharmony_ci{
370fb299fa2Sopenharmony_ci    std::vector<uint8_t> buff(sizeof(CentralDirEntry) + MAX_FILE_NAME);
371fb299fa2Sopenharmony_ci    size_t realLen = 0;
372fb299fa2Sopenharmony_ci    PkgFileImpl::ConvertStringToBuffer(fileInfo_.fileInfo.identity, {
373fb299fa2Sopenharmony_ci        buff.data() + sizeof(CentralDirEntry), buff.capacity()
374fb299fa2Sopenharmony_ci    }, realLen);
375fb299fa2Sopenharmony_ci
376fb299fa2Sopenharmony_ci    CentralDirEntry* centralDir = reinterpret_cast<CentralDirEntry*>(buff.data());
377fb299fa2Sopenharmony_ci    centralDir->signature = CENTRAL_SIGNATURE;
378fb299fa2Sopenharmony_ci    centralDir->versionMade = 0;
379fb299fa2Sopenharmony_ci    centralDir->versionNeeded = 0;
380fb299fa2Sopenharmony_ci    if (fileInfo_.method == Z_DEFLATED) {
381fb299fa2Sopenharmony_ci        centralDir->flags |= GPBDD_FLAG_MASK;
382fb299fa2Sopenharmony_ci    }
383fb299fa2Sopenharmony_ci    centralDir->compressionMethod = static_cast<uint16_t>(fileInfo_.method);
384fb299fa2Sopenharmony_ci    centralDir->crc = crc32_;
385fb299fa2Sopenharmony_ci    uint16_t date;
386fb299fa2Sopenharmony_ci    uint16_t time;
387fb299fa2Sopenharmony_ci    ExtraTimeAndDate(fileInfo_.fileInfo.modifiedTime, date, time);
388fb299fa2Sopenharmony_ci    centralDir->modifiedDate = date;
389fb299fa2Sopenharmony_ci    centralDir->modifiedTime = time;
390fb299fa2Sopenharmony_ci    centralDir->compressedSize = fileInfo_.fileInfo.packedSize;
391fb299fa2Sopenharmony_ci    centralDir->uncompressedSize = fileInfo_.fileInfo.unpackedSize;
392fb299fa2Sopenharmony_ci    centralDir->nameSize = realLen;
393fb299fa2Sopenharmony_ci    centralDir->extraSize = 0;
394fb299fa2Sopenharmony_ci    centralDir->commentSize = 0;
395fb299fa2Sopenharmony_ci    centralDir->diskNumStart = 0;
396fb299fa2Sopenharmony_ci    centralDir->internalAttr = 0;
397fb299fa2Sopenharmony_ci    centralDir->externalAttr = 0;
398fb299fa2Sopenharmony_ci    centralDir->localHeaderOffset = fileInfo_.fileInfo.headerOffset;
399fb299fa2Sopenharmony_ci    PkgBuffer buffer(buff);
400fb299fa2Sopenharmony_ci    int32_t ret = stream->Write(buffer, sizeof(CentralDirEntry) + realLen, startOffset);
401fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
402fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to write CentralDirEntry for %s", fileInfo_.fileInfo.identity.c_str());
403fb299fa2Sopenharmony_ci        return ret;
404fb299fa2Sopenharmony_ci    }
405fb299fa2Sopenharmony_ci    encodeLen = sizeof(CentralDirEntry) + realLen;
406fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
407fb299fa2Sopenharmony_ci}
408fb299fa2Sopenharmony_ci
409fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeLocalFileHeader(uint8_t *buffer, size_t bufferLen, bool hasDataDesc,
410fb299fa2Sopenharmony_ci    size_t nameLen)
411fb299fa2Sopenharmony_ci{
412fb299fa2Sopenharmony_ci    if (bufferLen < sizeof(LocalFileHeader)) {
413fb299fa2Sopenharmony_ci        PKG_LOGE("invalid buffer for decode");
414fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
415fb299fa2Sopenharmony_ci    }
416fb299fa2Sopenharmony_ci
417fb299fa2Sopenharmony_ci    LocalFileHeader* header = reinterpret_cast<LocalFileHeader*>(buffer);
418fb299fa2Sopenharmony_ci    header->signature = LOCAL_HEADER_SIGNATURE;
419fb299fa2Sopenharmony_ci    header->versionNeeded = 0;
420fb299fa2Sopenharmony_ci    header->flags = 0;
421fb299fa2Sopenharmony_ci    header->compressionMethod = static_cast<uint16_t>(fileInfo_.method);
422fb299fa2Sopenharmony_ci    uint16_t date;
423fb299fa2Sopenharmony_ci    uint16_t time;
424fb299fa2Sopenharmony_ci    ExtraTimeAndDate(fileInfo_.fileInfo.modifiedTime, date, time);
425fb299fa2Sopenharmony_ci    header->modifiedDate = date;
426fb299fa2Sopenharmony_ci    header->modifiedTime = time;
427fb299fa2Sopenharmony_ci    header->crc = crc32_;
428fb299fa2Sopenharmony_ci    header->compressedSize = fileInfo_.fileInfo.packedSize;
429fb299fa2Sopenharmony_ci    header->uncompressedSize = fileInfo_.fileInfo.unpackedSize;
430fb299fa2Sopenharmony_ci    header->nameSize = nameLen;
431fb299fa2Sopenharmony_ci    header->extraSize = 0;
432fb299fa2Sopenharmony_ci    if (hasDataDesc) {
433fb299fa2Sopenharmony_ci        header->flags |= GPBDD_FLAG_MASK;
434fb299fa2Sopenharmony_ci        header->compressedSize = 0u;
435fb299fa2Sopenharmony_ci        header->uncompressedSize = 0u;
436fb299fa2Sopenharmony_ci        header->crc = 0u;
437fb299fa2Sopenharmony_ci    }
438fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
439fb299fa2Sopenharmony_ci}
440fb299fa2Sopenharmony_ci
441fb299fa2Sopenharmony_ciint32_t ZipFileEntry::EncodeDataDescriptor(const PkgStreamPtr stream, size_t startOffset,
442fb299fa2Sopenharmony_ci    uint32_t &encodeLen) const
443fb299fa2Sopenharmony_ci{
444fb299fa2Sopenharmony_ci    int32_t ret = PKG_SUCCESS;
445fb299fa2Sopenharmony_ci    size_t offset = startOffset;
446fb299fa2Sopenharmony_ci    DataDescriptor dataDesc = {};
447fb299fa2Sopenharmony_ci    dataDesc.signature = DATA_DESC_SIGNATURE;
448fb299fa2Sopenharmony_ci    dataDesc.crc = crc32_;
449fb299fa2Sopenharmony_ci    dataDesc.compressedSize = fileInfo_.fileInfo.packedSize;
450fb299fa2Sopenharmony_ci    dataDesc.uncompressedSize = fileInfo_.fileInfo.unpackedSize;
451fb299fa2Sopenharmony_ci    PkgBuffer buffer((uint8_t *)&dataDesc, sizeof(dataDesc));
452fb299fa2Sopenharmony_ci    ret = stream->Write(buffer, sizeof(dataDesc), offset);
453fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
454fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to write DataDescriptor for %s", fileInfo_.fileInfo.identity.c_str());
455fb299fa2Sopenharmony_ci        return ret;
456fb299fa2Sopenharmony_ci    }
457fb299fa2Sopenharmony_ci    offset += sizeof(dataDesc);
458fb299fa2Sopenharmony_ci    encodeLen = offset - startOffset;
459fb299fa2Sopenharmony_ci    return ret;
460fb299fa2Sopenharmony_ci}
461fb299fa2Sopenharmony_ci
462fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DoDecodeCentralDirEntry(PkgBuffer &buffer, size_t &decodeLen,
463fb299fa2Sopenharmony_ci    size_t currLen, uint16_t nameSize, uint16_t extraSize)
464fb299fa2Sopenharmony_ci{
465fb299fa2Sopenharmony_ci    fileInfo_.method = static_cast<int32_t>(ReadLE16(buffer.buffer + offsetof(CentralDirEntry, compressionMethod)));
466fb299fa2Sopenharmony_ci    uint16_t modifiedTime = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedTime));
467fb299fa2Sopenharmony_ci    uint16_t modifiedDate = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, modifiedDate));
468fb299fa2Sopenharmony_ci    CombineTimeAndDate(fileInfo_.fileInfo.modifiedTime, modifiedTime, modifiedDate);
469fb299fa2Sopenharmony_ci    crc32_ = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, crc));
470fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packedSize = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, compressedSize));
471fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.unpackedSize = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, uncompressedSize));
472fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.headerOffset = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, localHeaderOffset));
473fb299fa2Sopenharmony_ci    // 对于zip64,需要解析extra field
474fb299fa2Sopenharmony_ci    decodeLen = currLen;
475fb299fa2Sopenharmony_ci    if (extraSize <= 0) {
476fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
477fb299fa2Sopenharmony_ci    }
478fb299fa2Sopenharmony_ci    uint8_t* extraData = buffer.buffer + nameSize + sizeof(CentralDirEntry);
479fb299fa2Sopenharmony_ci    uint16_t headerId = ReadLE16(extraData);
480fb299fa2Sopenharmony_ci    if (headerId != 1) { // zip64 扩展
481fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
482fb299fa2Sopenharmony_ci    }
483fb299fa2Sopenharmony_ci    size_t unpackedSize = ReadLE64(extraData + sizeof(uint32_t));
484fb299fa2Sopenharmony_ci    size_t packedSize = ReadLE64(extraData + sizeof(uint32_t) + sizeof(uint64_t));
485fb299fa2Sopenharmony_ci    if (fileInfo_.fileInfo.packedSize == UINT_MAX || fileInfo_.fileInfo.unpackedSize == UINT_MAX) {
486fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize =
487fb299fa2Sopenharmony_ci            (fileInfo_.fileInfo.unpackedSize == UINT_MAX) ? unpackedSize : fileInfo_.fileInfo.unpackedSize;
488fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.packedSize =
489fb299fa2Sopenharmony_ci            (fileInfo_.fileInfo.packedSize == UINT_MAX) ? packedSize : fileInfo_.fileInfo.packedSize;
490fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.headerOffset = (fileInfo_.fileInfo.headerOffset == UINT_MAX) ?
491fb299fa2Sopenharmony_ci            ReadLE64(extraData + BIG_SIZE_HEADER) : fileInfo_.fileInfo.headerOffset;
492fb299fa2Sopenharmony_ci    } else if (fileInfo_.fileInfo.headerOffset == UINT_MAX) {
493fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.headerOffset = unpackedSize;
494fb299fa2Sopenharmony_ci    }
495fb299fa2Sopenharmony_ci
496fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
497fb299fa2Sopenharmony_ci}
498fb299fa2Sopenharmony_ci
499fb299fa2Sopenharmony_ci/*
500fb299fa2Sopenharmony_ci    0x0001     2 bytes    Tag for this "extra" block type
501fb299fa2Sopenharmony_ci    Size       2 bytes    Size of this "extra" block
502fb299fa2Sopenharmony_ci        Original
503fb299fa2Sopenharmony_ci    Size       8 bytes    Original uncompressed file size
504fb299fa2Sopenharmony_ci    Compressed
505fb299fa2Sopenharmony_ci    Size       8 bytes    Size of compressed data
506fb299fa2Sopenharmony_ci    Relative Header
507fb299fa2Sopenharmony_ci    Offset     8 bytes    Offset of local header record
508fb299fa2Sopenharmony_ci    Disk Start
509fb299fa2Sopenharmony_ci    Number     4 bytes    Number of the disk on which
510fb299fa2Sopenharmony_ci    this file starts
511fb299fa2Sopenharmony_ci*/
512fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeCentralDirEntry(PkgStreamPtr inStream, PkgBuffer &buffer, size_t currentPos,
513fb299fa2Sopenharmony_ci    size_t &decodeLen)
514fb299fa2Sopenharmony_ci{
515fb299fa2Sopenharmony_ci    size_t readLen = buffer.length;
516fb299fa2Sopenharmony_ci    if (readLen < sizeof(CentralDirEntry)) {
517fb299fa2Sopenharmony_ci        PKG_LOGE("data not not enough %zu", readLen);
518fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
519fb299fa2Sopenharmony_ci    }
520fb299fa2Sopenharmony_ci    uint32_t signature = ReadLE32(buffer.buffer + offsetof(CentralDirEntry, signature));
521fb299fa2Sopenharmony_ci    if (signature != CENTRAL_SIGNATURE) {
522fb299fa2Sopenharmony_ci        PKG_LOGE("Check centralDir signature failed 0x%x", signature);
523fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
524fb299fa2Sopenharmony_ci    }
525fb299fa2Sopenharmony_ci    uint16_t nameSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, nameSize));
526fb299fa2Sopenharmony_ci    uint16_t extraSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, extraSize));
527fb299fa2Sopenharmony_ci    uint16_t commentSize = ReadLE16(buffer.buffer + offsetof(CentralDirEntry, commentSize));
528fb299fa2Sopenharmony_ci    size_t currLen = sizeof(CentralDirEntry) + nameSize + extraSize + commentSize;
529fb299fa2Sopenharmony_ci    if (currentPos >= (std::numeric_limits<size_t>::max() - currLen)) {
530fb299fa2Sopenharmony_ci        PKG_LOGE("check centralDir len failed");
531fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
532fb299fa2Sopenharmony_ci    }
533fb299fa2Sopenharmony_ci    size_t fileNameLength = nameSize;
534fb299fa2Sopenharmony_ci    if (nameSize >= MAX_FILE_NAME) {
535fb299fa2Sopenharmony_ci        PKG_LOGE("file name size too longer %d", nameSize);
536fb299fa2Sopenharmony_ci        fileNameLength = MAX_FILE_NAME - 1;
537fb299fa2Sopenharmony_ci    }
538fb299fa2Sopenharmony_ci    if (readLen < sizeof(CentralDirEntry) + fileNameLength) {
539fb299fa2Sopenharmony_ci        PKG_LOGE("data not not enough %zu", readLen);
540fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
541fb299fa2Sopenharmony_ci    }
542fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.identity.assign(reinterpret_cast<char*>(buffer.buffer + sizeof(CentralDirEntry)),
543fb299fa2Sopenharmony_ci                                       fileNameLength);
544fb299fa2Sopenharmony_ci    return DoDecodeCentralDirEntry(buffer, decodeLen, currLen, nameSize, extraSize);
545fb299fa2Sopenharmony_ci}
546fb299fa2Sopenharmony_ci
547fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeLocalFileHeaderCheck(PkgStreamPtr inStream, PkgBuffer &data,
548fb299fa2Sopenharmony_ci    size_t currentPos)
549fb299fa2Sopenharmony_ci{
550fb299fa2Sopenharmony_ci    uint16_t flags = ReadLE16(data.buffer + offsetof(LocalFileHeader, flags));
551fb299fa2Sopenharmony_ci    uint32_t crc32 = ReadLE32(data.buffer + offsetof(LocalFileHeader, crc));
552fb299fa2Sopenharmony_ci    uint32_t packedSize = ReadLE32(data.buffer + offsetof(LocalFileHeader, compressedSize));
553fb299fa2Sopenharmony_ci    uint32_t unpackedSize = ReadLE32(data.buffer + offsetof(LocalFileHeader, uncompressedSize));
554fb299fa2Sopenharmony_ci    size_t readLen = 0;
555fb299fa2Sopenharmony_ci    if ((flags & GPBDD_FLAG_MASK) == GPBDD_FLAG_MASK) {
556fb299fa2Sopenharmony_ci        currentPos += fileInfo_.fileInfo.packedSize;
557fb299fa2Sopenharmony_ci        int ret = inStream->Read(data, currentPos, data.length, readLen);
558fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
559fb299fa2Sopenharmony_ci            PKG_LOGE("parse entry read centralDir failed");
560fb299fa2Sopenharmony_ci            return ret;
561fb299fa2Sopenharmony_ci        }
562fb299fa2Sopenharmony_ci        if (readLen < sizeof(DataDescriptor)) {
563fb299fa2Sopenharmony_ci            PKG_LOGE("data not not enough %zu", readLen);
564fb299fa2Sopenharmony_ci            return PKG_INVALID_PKG_FORMAT;
565fb299fa2Sopenharmony_ci        }
566fb299fa2Sopenharmony_ci
567fb299fa2Sopenharmony_ci        uint32_t signature = ReadLE32(data.buffer + offsetof(DataDescriptor, signature));
568fb299fa2Sopenharmony_ci        if (signature != DATA_DESC_SIGNATURE) {
569fb299fa2Sopenharmony_ci            PKG_LOGE("check DataDescriptor signature failed");
570fb299fa2Sopenharmony_ci            return PKG_INVALID_PKG_FORMAT;
571fb299fa2Sopenharmony_ci        }
572fb299fa2Sopenharmony_ci        crc32 = ReadLE32(data.buffer + offsetof(DataDescriptor, crc));
573fb299fa2Sopenharmony_ci        packedSize = ReadLE32(data.buffer + offsetof(DataDescriptor, compressedSize));
574fb299fa2Sopenharmony_ci        unpackedSize = ReadLE32(data.buffer + offsetof(DataDescriptor, uncompressedSize));
575fb299fa2Sopenharmony_ci    }
576fb299fa2Sopenharmony_ci    PKG_LOGI("DecodeLocalFileHeaderCheck: packedSize: %zu unpackedSize: %zu", packedSize, unpackedSize);
577fb299fa2Sopenharmony_ci    if (crc32_ != crc32) {
578fb299fa2Sopenharmony_ci        PKG_LOGE("check crc %u %u failed", crc32_, crc32);
579fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
580fb299fa2Sopenharmony_ci    }
581fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
582fb299fa2Sopenharmony_ci}
583fb299fa2Sopenharmony_ci
584fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeLocalFileHeader(PkgStreamPtr inStream, PkgBuffer &data, size_t currentPos,
585fb299fa2Sopenharmony_ci    size_t &decodeLen)
586fb299fa2Sopenharmony_ci{
587fb299fa2Sopenharmony_ci    size_t readLen = 0;
588fb299fa2Sopenharmony_ci    int32_t ret = inStream->Read(data, currentPos, data.length, readLen);
589fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
590fb299fa2Sopenharmony_ci        PKG_LOGE("parse entry read centralDir failed");
591fb299fa2Sopenharmony_ci        return ret;
592fb299fa2Sopenharmony_ci    }
593fb299fa2Sopenharmony_ci    if (readLen < sizeof(LocalFileHeader)) {
594fb299fa2Sopenharmony_ci        PKG_LOGE("data not not enough %zu", readLen);
595fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
596fb299fa2Sopenharmony_ci    }
597fb299fa2Sopenharmony_ci    uint32_t signature = ReadLE32(data.buffer + offsetof(LocalFileHeader, signature));
598fb299fa2Sopenharmony_ci    if (signature != LOCAL_HEADER_SIGNATURE) {
599fb299fa2Sopenharmony_ci        PKG_LOGE("check localHeader signature failed");
600fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
601fb299fa2Sopenharmony_ci    }
602fb299fa2Sopenharmony_ci
603fb299fa2Sopenharmony_ci    uint16_t nameSize = ReadLE16(data.buffer + offsetof(LocalFileHeader, nameSize));
604fb299fa2Sopenharmony_ci    uint16_t extraSize = ReadLE16(data.buffer + offsetof(LocalFileHeader, extraSize));
605fb299fa2Sopenharmony_ci    size_t currLen = sizeof(LocalFileHeader) + nameSize + extraSize;
606fb299fa2Sopenharmony_ci    if (currentPos >= (std::numeric_limits<size_t>::max() - currLen)) {
607fb299fa2Sopenharmony_ci        PKG_LOGE("check centralDir len failed");
608fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
609fb299fa2Sopenharmony_ci    }
610fb299fa2Sopenharmony_ci    size_t fileNameLength = (nameSize >= MAX_FILE_NAME) ? MAX_FILE_NAME - 1 : nameSize;
611fb299fa2Sopenharmony_ci    if (readLen < sizeof(LocalFileHeader) + fileNameLength) {
612fb299fa2Sopenharmony_ci        PKG_LOGE("data not not enough %zu", readLen);
613fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
614fb299fa2Sopenharmony_ci    }
615fb299fa2Sopenharmony_ci    std::string fileName(reinterpret_cast<char*>(data.buffer + sizeof(LocalFileHeader)), fileNameLength);
616fb299fa2Sopenharmony_ci    uint16_t compressionMethod = ReadLE16(data.buffer + offsetof(LocalFileHeader, compressionMethod));
617fb299fa2Sopenharmony_ci    fileInfo_.method = static_cast<int32_t>(compressionMethod);
618fb299fa2Sopenharmony_ci    fileInfo_.level = Z_BEST_COMPRESSION;
619fb299fa2Sopenharmony_ci    fileInfo_.windowBits = -MAX_WBITS;
620fb299fa2Sopenharmony_ci    fileInfo_.memLevel = DEF_MEM_LEVEL;
621fb299fa2Sopenharmony_ci    fileInfo_.strategy = Z_DEFAULT_STRATEGY;
622fb299fa2Sopenharmony_ci    if (fileInfo_.fileInfo.identity.compare(fileName)) {
623fb299fa2Sopenharmony_ci        PKG_LOGE("check file name %s %s failed", fileInfo_.fileInfo.identity.c_str(), fileName.c_str());
624fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
625fb299fa2Sopenharmony_ci    }
626fb299fa2Sopenharmony_ci    fileName_.assign(fileInfo_.fileInfo.identity);
627fb299fa2Sopenharmony_ci    decodeLen = currLen;
628fb299fa2Sopenharmony_ci
629fb299fa2Sopenharmony_ci    // 检查解析的是否正确
630fb299fa2Sopenharmony_ci    ret = DecodeLocalFileHeaderCheck(inStream, data, currentPos + currLen);
631fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
632fb299fa2Sopenharmony_ci        return ret;
633fb299fa2Sopenharmony_ci    }
634fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
635fb299fa2Sopenharmony_ci}
636fb299fa2Sopenharmony_ci
637fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Stored(const PkgStreamPtr inStream, const PkgStreamPtr outStream,
638fb299fa2Sopenharmony_ci    PkgAlgorithmContext &context)
639fb299fa2Sopenharmony_ci{
640fb299fa2Sopenharmony_ci    size_t start = 0;
641fb299fa2Sopenharmony_ci    size_t startWrite = 0;
642fb299fa2Sopenharmony_ci    size_t remainSize = context.packedSize;
643fb299fa2Sopenharmony_ci    while (remainSize > 0) {
644fb299fa2Sopenharmony_ci        PkgBuffer buffer(MAX_BUFFER_SIZE);
645fb299fa2Sopenharmony_ci        size_t readLen = (remainSize > buffer.length) ? buffer.length : remainSize;
646fb299fa2Sopenharmony_ci        int32_t ret = inStream->Read(buffer, context.srcOffset, readLen, start);
647fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
648fb299fa2Sopenharmony_ci            PKG_LOGE("read buffer from inStream failed");
649fb299fa2Sopenharmony_ci            return ret;
650fb299fa2Sopenharmony_ci        }
651fb299fa2Sopenharmony_ci        ret = outStream->Write(buffer, readLen, startWrite);
652fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
653fb299fa2Sopenharmony_ci            PKG_LOGE("write buffer in outStream failed");
654fb299fa2Sopenharmony_ci            return ret;
655fb299fa2Sopenharmony_ci        }
656fb299fa2Sopenharmony_ci        startWrite += readLen;
657fb299fa2Sopenharmony_ci        remainSize -= readLen;
658fb299fa2Sopenharmony_ci    }
659fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
660fb299fa2Sopenharmony_ci}
661fb299fa2Sopenharmony_ci
662fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Unpack(PkgStreamPtr outStream)
663fb299fa2Sopenharmony_ci{
664fb299fa2Sopenharmony_ci    PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
665fb299fa2Sopenharmony_ci    if (algorithm == nullptr) {
666fb299fa2Sopenharmony_ci        PKG_LOGE("ZipFileEntry::Unpack : can not algorithm for %s", fileInfo_.fileInfo.identity.c_str());
667fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
668fb299fa2Sopenharmony_ci    }
669fb299fa2Sopenharmony_ci
670fb299fa2Sopenharmony_ci    PkgStreamPtr inStream = pkgFile_->GetPkgStream();
671fb299fa2Sopenharmony_ci    if (outStream == nullptr || inStream == nullptr) {
672fb299fa2Sopenharmony_ci        PKG_LOGE("ZipFileEntry::Unpack : outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
673fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
674fb299fa2Sopenharmony_ci    }
675fb299fa2Sopenharmony_ci    PkgAlgorithmContext context = {
676fb299fa2Sopenharmony_ci        {this->fileInfo_.fileInfo.dataOffset, 0},
677fb299fa2Sopenharmony_ci        {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
678fb299fa2Sopenharmony_ci        crc32_, fileInfo_.fileInfo.digestMethod
679fb299fa2Sopenharmony_ci    };
680fb299fa2Sopenharmony_ci    int32_t ret = PKG_SUCCESS;
681fb299fa2Sopenharmony_ci    switch (fileInfo_.method) {
682fb299fa2Sopenharmony_ci        case Z_DEFLATED:
683fb299fa2Sopenharmony_ci            ret = algorithm->Unpack(inStream, outStream, context);
684fb299fa2Sopenharmony_ci            break;
685fb299fa2Sopenharmony_ci        case Z_STORED:
686fb299fa2Sopenharmony_ci            ret = Stored(inStream, outStream, context);
687fb299fa2Sopenharmony_ci            break;
688fb299fa2Sopenharmony_ci        default:
689fb299fa2Sopenharmony_ci            ret = PKG_INVALID_PARAM;
690fb299fa2Sopenharmony_ci            break;
691fb299fa2Sopenharmony_ci    }
692fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
693fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to decompress for %s", fileInfo_.fileInfo.identity.c_str());
694fb299fa2Sopenharmony_ci        return ret;
695fb299fa2Sopenharmony_ci    }
696fb299fa2Sopenharmony_ci    PKG_LOGI("packedSize: %zu unpackedSize: %zu  offset header: %zu data: %zu", fileInfo_.fileInfo.packedSize,
697fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.unpackedSize, fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset);
698fb299fa2Sopenharmony_ci    ret = outStream->Flush(fileInfo_.fileInfo.unpackedSize);
699fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
700fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to Flush for %s", fileInfo_.fileInfo.identity.c_str());
701fb299fa2Sopenharmony_ci        return ret;
702fb299fa2Sopenharmony_ci    }
703fb299fa2Sopenharmony_ci    algorithm->UpdateFileInfo(&fileInfo_.fileInfo);
704fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
705fb299fa2Sopenharmony_ci}
706fb299fa2Sopenharmony_ci
707fb299fa2Sopenharmony_civoid ZipFileEntry::CombineTimeAndDate(time_t &time, uint16_t modifiedTime, uint16_t modifiedDate) const
708fb299fa2Sopenharmony_ci{
709fb299fa2Sopenharmony_ci    struct tm newTime;
710fb299fa2Sopenharmony_ci    newTime.tm_year = ((modifiedDate >> TM_YEAR_BITS) & 0x7f) + START_YEAR; // 年,tm_year为int临时变量减去1900。
711fb299fa2Sopenharmony_ci    newTime.tm_mon = (modifiedDate >> TM_MON_BITS) & 0xf; // 月,tm_mon为int临时变量减去1。
712fb299fa2Sopenharmony_ci    newTime.tm_mday = modifiedDate & 0x1f;         // 日。
713fb299fa2Sopenharmony_ci    newTime.tm_hour = (modifiedTime >> TM_HOUR_BITS) & 0x1f; // 时。
714fb299fa2Sopenharmony_ci    newTime.tm_min = (modifiedTime >> TM_MIN_BITS) & 0x2f;   // 分。
715fb299fa2Sopenharmony_ci    newTime.tm_sec = (modifiedTime << 1) & 0x1f;   // 秒。
716fb299fa2Sopenharmony_ci    newTime.tm_isdst = 0;                          // 非夏令时。
717fb299fa2Sopenharmony_ci    time = mktime(&newTime);                      // 将tm结构体转换成time_t格式。
718fb299fa2Sopenharmony_ci}
719fb299fa2Sopenharmony_ci
720fb299fa2Sopenharmony_ciint32_t ZipFileEntry::DecodeHeader(PkgBuffer &buffer, size_t headerOffset, size_t dataOffset,
721fb299fa2Sopenharmony_ci    size_t &decodeLen)
722fb299fa2Sopenharmony_ci{
723fb299fa2Sopenharmony_ci    PkgStreamPtr inStream = pkgFile_->GetPkgStream();
724fb299fa2Sopenharmony_ci    if (inStream == nullptr) {
725fb299fa2Sopenharmony_ci        PKG_LOGE("outStream or inStream null for %s", fileInfo_.fileInfo.identity.c_str());
726fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
727fb299fa2Sopenharmony_ci    }
728fb299fa2Sopenharmony_ci
729fb299fa2Sopenharmony_ci    if (headerOffset >= (std::numeric_limits<size_t>::max() - buffer.length)) {
730fb299fa2Sopenharmony_ci        PKG_LOGE("check centralDir len failed");
731fb299fa2Sopenharmony_ci        return PKG_INVALID_PKG_FORMAT;
732fb299fa2Sopenharmony_ci    }
733fb299fa2Sopenharmony_ci    size_t readLen = 0;
734fb299fa2Sopenharmony_ci    int32_t ret = inStream->Read(buffer, headerOffset, buffer.length, readLen);
735fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
736fb299fa2Sopenharmony_ci        PKG_LOGE("parse entry read centralDir failed");
737fb299fa2Sopenharmony_ci        return ret;
738fb299fa2Sopenharmony_ci    }
739fb299fa2Sopenharmony_ci    PkgBuffer centralBuff(buffer.buffer, readLen);
740fb299fa2Sopenharmony_ci    ret = DecodeCentralDirEntry(inStream, centralBuff, headerOffset, decodeLen);
741fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
742fb299fa2Sopenharmony_ci        PKG_LOGE("decode CentralDir failed");
743fb299fa2Sopenharmony_ci        return ret;
744fb299fa2Sopenharmony_ci    }
745fb299fa2Sopenharmony_ci
746fb299fa2Sopenharmony_ci    size_t headerLen = 0;
747fb299fa2Sopenharmony_ci    ret = DecodeLocalFileHeader(inStream, buffer, fileInfo_.fileInfo.headerOffset, headerLen);
748fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
749fb299fa2Sopenharmony_ci        PKG_LOGE("decode LocalFileHeader failed");
750fb299fa2Sopenharmony_ci        return ret;
751fb299fa2Sopenharmony_ci    }
752fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
753fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
754fb299fa2Sopenharmony_ci    fileInfo_.fileInfo.dataOffset = fileInfo_.fileInfo.headerOffset + headerLen;
755fb299fa2Sopenharmony_ci    PKG_LOGI("packedSize: %zu unpackedSize: %zu  offset header: %zu data: %zu %s",
756fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize,
757fb299fa2Sopenharmony_ci        fileInfo_.fileInfo.headerOffset, fileInfo_.fileInfo.dataOffset, fileInfo_.fileInfo.identity.c_str());
758fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
759fb299fa2Sopenharmony_ci}
760fb299fa2Sopenharmony_ci
761fb299fa2Sopenharmony_ciint32_t ZipFileEntry::Init(const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream)
762fb299fa2Sopenharmony_ci{
763fb299fa2Sopenharmony_ci    fileInfo_.level = Z_BEST_COMPRESSION;
764fb299fa2Sopenharmony_ci    fileInfo_.method = Z_DEFLATED;
765fb299fa2Sopenharmony_ci    fileInfo_.windowBits = -MAX_WBITS;
766fb299fa2Sopenharmony_ci    fileInfo_.memLevel = DEF_MEM_LEVEL;
767fb299fa2Sopenharmony_ci    fileInfo_.strategy = Z_DEFAULT_STRATEGY;
768fb299fa2Sopenharmony_ci    int32_t ret = PkgEntry::Init(&fileInfo_.fileInfo, fileInfo, inStream);
769fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
770fb299fa2Sopenharmony_ci        PKG_LOGE("Failed to check input param");
771fb299fa2Sopenharmony_ci        return PKG_INVALID_PARAM;
772fb299fa2Sopenharmony_ci    }
773fb299fa2Sopenharmony_ci    ZipFileInfo* info = (ZipFileInfo*)fileInfo;
774fb299fa2Sopenharmony_ci    if (info != nullptr && info->method != -1) {
775fb299fa2Sopenharmony_ci        fileInfo_.level = info->level;
776fb299fa2Sopenharmony_ci        fileInfo_.memLevel = info->memLevel;
777fb299fa2Sopenharmony_ci        fileInfo_.method = info->method;
778fb299fa2Sopenharmony_ci        fileInfo_.strategy = info->strategy;
779fb299fa2Sopenharmony_ci        fileInfo_.windowBits = info->windowBits;
780fb299fa2Sopenharmony_ci    }
781fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
782fb299fa2Sopenharmony_ci}
783fb299fa2Sopenharmony_ci} // namespace Hpackage
784