1/*
2 * Copyright (c) 2024 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#include <filesystem>
17#include <fstream>
18#include <iostream>
19#include <sstream>
20#include <string>
21
22#include "packager.h"
23
24namespace OHOS {
25namespace AppPackingTool {
26namespace {}
27
28Packager::Packager(const std::map<std::string, std::string> &parameterMap, std::string &resultReceiver)
29    : parameterMap_(parameterMap), resultReceiver_(resultReceiver)
30{}
31
32Packager::~Packager() {}
33
34std::string Packager::MakePackage()
35{
36    if (InitAllowedParam() != ERR_OK) {
37        std::cout << "PreCheck err" << std::endl;
38    }
39
40    if (PreProcess() != ERR_OK) {
41        std::cout << "PreCheck err" << std::endl;
42    }
43
44    if (Process() != ERR_OK) {
45        std::cout << "DoPackage err" << std::endl;
46    }
47
48    if (PostProcess() != ERR_OK) {
49        std::cout << "PostCheck err" << std::endl;
50    }
51
52    return "OHOS::ERR_OK";
53}
54
55int Packager::PreProcess()
56{
57    std::cout << "PreCheck" << std::endl;
58    resultReceiver_.append("do PreCheck\n");
59    return ERR_OK;
60}
61
62int Packager::Process()
63{
64    std::cout << "DoPackage" << std::endl;
65    resultReceiver_.append("do DoPackage\n");
66    return ERR_OK;
67}
68
69int Packager::PostProcess()
70{
71    std::cout << "PostCheck" << std::endl;
72    resultReceiver_.append("do PostCheck\n");
73    return ERR_OK;
74}
75
76void Packager::AddFileToZip(zipFile zf, const fs::path &filePath, const fs::path &zipPath, zip_fileinfo &zipfi)
77{
78    if (fs::is_directory(filePath)) {
79        for (const auto &entry : fs::directory_iterator(filePath)) {
80            fs::path tmpPath = zipPath / entry.path().filename();
81            AddFileToZip(zf, entry.path(), tmpPath, zipfi);
82        }
83    } else if (fs::is_regular_file(filePath)) {
84        std::ifstream file(filePath, std::ios::binary);
85        if (!file.is_open()) {
86            std::cout << "err opening file for read: " << filePath << std::endl;
87        }
88        int ret = zipOpenNewFileInZip(zf, zipPath.string().c_str(), &zipfi, nullptr, 0,
89            nullptr, 0, nullptr, 0, Z_DEFAULT_COMPRESSION);
90        if (ret != ZIP_OK) {
91            std::cout << "zipOpenNewFileInZip err: " << ret << ", " << filePath << std::endl;
92            file.close();
93            return ;
94        }
95        char buffer[Constants::BUF_SIZE];
96        while (file.good()) {
97            file.read(buffer, sizeof(buffer));
98            auto bytesRead = file.gcount();
99            if (bytesRead <= 0) {
100                std::cout << "read file: " << filePath << " err, bytesRead: " << bytesRead << std::endl;
101                break;
102            }
103            if (zipWriteInFileInZip(zf, buffer, bytesRead) < 0) {
104                std::cout << "err write to zip file: " << filePath << std::endl;
105                break;
106            }
107        }
108        zipCloseFileInZip(zf);
109        file.close();
110    }
111}
112
113void Packager::WriteStringToZip(zipFile zf, const std::string &content, const fs::path &zipPath, zip_fileinfo &zipfi)
114{
115    if (zipOpenNewFileInZip(zf, zipPath.string().c_str(), &zipfi, nullptr, 0, nullptr, 0, nullptr, 0,
116                            Z_DEFAULT_COMPRESSION) == ZIP_OK) {
117        if (zipWriteInFileInZip(zf, content.data(), content.length()) < 0) {
118            std::cout << "zipWriteInFileInZip err: " << errno << std::endl;
119        }
120        zipCloseFileInZip(zf);
121    }
122}
123
124bool Packager::ParseJsonFile(nlohmann::json &jsonObject, std::string filePath)
125{
126    std::ifstream i(filePath);
127    if (!i.is_open()) {
128        std::cout<<"failed to open json file, errno: " << errno << std::endl;
129        return false;
130    }
131    i.seekg(0, std::ios::end);
132    int len = static_cast<int>(i.tellg());
133    if (len == 0) {
134        i.close();
135        std::cout << "json file is empty" << std::endl;
136        return true;
137    }
138    i.seekg(0, std::ios::beg);
139    jsonObject = nlohmann::json::parse(i, nullptr, false);
140    if (jsonObject.is_discarded()) {
141        i.close();
142        std::cout << "ParseJsonFile failed due to data is discarded." << std::endl;
143        return false;
144    }
145    i.close();
146    return true;
147}
148
149bool Packager::endWith(const std::string &str, const std::string &suffix)
150{
151    if (str.length() >= suffix.length()) {
152        return str.compare(str.length() - suffix.length(), suffix.length(), suffix);
153    }
154    return false;
155}
156
157bool Packager::CheckFileValid(const std::string &filePath, const std::string &filename)
158{
159    if (fs::is_regular_file(filePath)) {
160        std::string name = fs::path(filePath).filename();
161        if (endWith(name, filename)) {
162            return true;
163        }
164    }
165    return false;
166}
167
168
169} // namespace AppPackingTool
170} // namespace OHOS