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 "package_normalize.h"
17
18 #include "json/json_utils.h"
19 #include "json/pack_info.h"
20 #include "log.h"
21 #include "utils.h"
22 #include "zip_utils.h"
23
24 namespace OHOS {
25 namespace AppPackingTool {
PackageNormalize(const std::map<std::string,std::string> & parameterMap,std::string & resultReceiver)26 PackageNormalize::PackageNormalize(const std::map<std::string, std::string> ¶meterMap, std::string &resultReceiver)
27 : Packager(parameterMap, resultReceiver)
28 {}
29
InitAllowedParam()30 int32_t PackageNormalize::InitAllowedParam()
31 {
32 allowedParameters_ = {
33 {}
34 };
35 return ERR_OK;
36 }
37
38
PreProcess()39 int32_t PackageNormalize::PreProcess()
40 {
41 if (!IsOutDirectoryValid()) {
42 return ERR_INVALID_VALUE;
43 }
44 auto it = parameterMap_.find(Constants::PARAM_HSP_LIST);
45 if (it == parameterMap_.end()) {
46 LOGE("hsp-list is empty.");
47 return ERR_INVALID_VALUE;
48 }
49 if (!CompatibleProcess(it->second, hspList_, Constants::HSP_SUFFIX)) {
50 LOGE("hsp-list is invalid.");
51 return ERR_INVALID_VALUE;
52 }
53 if (hspList_.empty()) {
54 LOGE("hsp-list is empty.");
55 return ERR_INVALID_VALUE;
56 }
57
58 it = parameterMap_.find(Constants::PARAM_BUNDLE_NAME);
59 std::regex pattern(Constants::BUNDLE_NAME_PATTERN);
60 if (it == parameterMap_.end() || it->second.length() < Constants::BUNDLE_NAME_LEN_MIN ||
61 it->second.length() > Constants::BUNDLE_NAME_LEN_MAX || !std::regex_match(it->second, pattern)) {
62 LOGE("bundle-name is invalid.");
63 return ERR_INVALID_VALUE;
64 }
65
66 it = parameterMap_.find(Constants::PARAM_VERSION_CODE);
67 if (it == parameterMap_.end() || !Utils::IsPositiveInteger(it->second)) {
68 LOGE("version-code is invalid.");
69 return ERR_INVALID_VALUE;
70 }
71 return ERR_OK;
72 }
73
ModifyModuleJson(const std::string & moduleJsonPath,const int32_t & newVersionCode,const std::string & newBundleName)74 bool PackageNormalize::ModifyModuleJson(const std::string &moduleJsonPath,
75 const int32_t &newVersionCode, const std::string &newBundleName)
76 {
77 ModuleJson moduleJson;
78 if (!moduleJson.ParseFromFile(moduleJsonPath)) {
79 LOGE("Update module.json failed, parse json is null.");
80 return false;
81 }
82 if (!moduleJson.SetBundleName(newBundleName)) {
83 LOGE("Parse and modify module.json failed, json file not valid.");
84 return false;
85 }
86 if (!moduleJson.SetStageVersionCode(newVersionCode)) {
87 LOGE("Parse and modify module.json failed, json file not valid.");
88 return false;
89 }
90 if (!JsonUtils::StrToFile(moduleJson.ToString(), moduleJsonPath)) {
91 LOGE("Parse and modify module.json failed, write Json failed.");
92 return false;
93 }
94 return true;
95 }
96
ModifyPackInfo(const std::string & packInfoPath,const int32_t & newVersionCode,const std::string & newBundleName)97 bool PackageNormalize::ModifyPackInfo(const std::string &packInfoPath,
98 const int32_t &newVersionCode, const std::string &newBundleName)
99 {
100 PackInfo packInfo;
101 if (!packInfo.ParseFromFile(packInfoPath)) {
102 LOGE("Update packInfo failed, parse json is null.");
103 return false;
104 }
105 if (!packInfo.SetBundleName(newBundleName)) {
106 LOGE("Parse and modify packInfo failed, json file not valid.");
107 return false;
108 }
109 if (!packInfo.SetVersionCode(newVersionCode)) {
110 LOGE("Parse and modify packInfo failed, json file not valid.");
111 return false;
112 }
113 if (!JsonUtils::StrToFile(packInfo.ToString(), packInfoPath)) {
114 LOGE("Parse and modify packinfo failed, write Json failed.");
115 return false;
116 }
117 return true;
118 }
119
Process()120 int32_t PackageNormalize::Process()
121 {
122 std::string outPath = parameterMap_.at(Constants::PARAM_OUT_PATH);
123 std::string tempPath = outPath + Constants::LINUX_FILE_SEPARATOR + Constants::COMPRESSOR_PACKAGENORMALIZE_TEMP_DIR
124 + Utils::GenerateUUID();
125 int32_t versionCode = 0;
126 auto it = parameterMap_.find(Constants::PARAM_VERSION_CODE);
127 if (it != parameterMap_.end()) {
128 try {
129 versionCode = std::stoi(it->second);
130 } catch (const std::exception& e) {
131 LOGE("Exception: %s", e.what());
132 return ERR_INVALID_VALUE;
133 }
134 } else {
135 LOGE("Parameter not found: %s", Constants::PARAM_VERSION_CODE.c_str());
136 return ERR_INVALID_VALUE;
137 }
138 std::string bundleName = parameterMap_.at(Constants::PARAM_BUNDLE_NAME);
139 for (const std::string &path : hspList_) {
140 if (ZipUtils::Unzip(path, tempPath) != ZIP_ERR_SUCCESS) {
141 Utils::ForceRemoveDirectory(tempPath);
142 return ERR_INVALID_VALUE;
143 }
144 std::string moduleJsonPath = tempPath + Constants::LINUX_FILE_SEPARATOR + Constants::MODULE_JSON;
145 std::string packInfoPath = tempPath + Constants::LINUX_FILE_SEPARATOR + Constants::PACK_INFO;
146 fs::path entryPath(path);
147 std::string filePath = entryPath.filename().string();
148 if (!fs::exists(moduleJsonPath) || !fs::is_regular_file(moduleJsonPath) || !fs::exists(packInfoPath) ||
149 !fs::is_regular_file(packInfoPath)) {
150 LOGE("PackageNormalize failed: hsp not have file module.json or pack.info.");
151 Utils::ForceRemoveDirectory(tempPath);
152 return ERR_INVALID_VALUE;
153 }
154
155 if (!ModifyModuleJson(moduleJsonPath, versionCode, bundleName)) {
156 Utils::ForceRemoveDirectory(tempPath);
157 return ERR_INVALID_VALUE;
158 }
159 if (!ModifyPackInfo(packInfoPath, versionCode, bundleName)) {
160 Utils::ForceRemoveDirectory(tempPath);
161 return ERR_INVALID_VALUE;
162 }
163 if (ZipUtils::Zip(tempPath, outPath + Constants::LINUX_FILE_SEPARATOR + filePath) != ZIP_ERR_SUCCESS) {
164 Utils::ForceRemoveDirectory(tempPath);
165 return ERR_INVALID_VALUE;
166 }
167 Utils::ForceRemoveDirectory(tempPath);
168 }
169 return ERR_OK;
170 }
171
PostProcess()172 int32_t PackageNormalize::PostProcess()
173 {
174 return ERR_OK;
175 }
176 } // namespace AppPackingTool
177 } // namespace OHOS