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 "pack_info_utils.h"
17 
18 #include <fstream>
19 
20 #include "log.h"
21 
22 namespace OHOS {
23 namespace AppPackingTool {
24 namespace {
25 const std::string DEFAULT_BUNDLE_TYPE = "APP";
26 const std::string MODULE = "module";
27 const std::string PACKAGES = "packages";
28 const char DOT = '.';
29 }
30 
31 // java : mergeTwoPackInfo
MergeTwoPackInfos(const std::string& srcPackInfoJsonStr1, const std::string& srcPackInfoJsonStr2, std::string& dstPackInfoJsonStr)32 bool PackInfoUtils::MergeTwoPackInfos(const std::string& srcPackInfoJsonStr1, const std::string& srcPackInfoJsonStr2,
33     std::string& dstPackInfoJsonStr)
34 {
35     PackInfo srcPackInfo1;
36     PackInfo srcPackInfo2;
37     if (!srcPackInfo1.ParseFromString(srcPackInfoJsonStr1)) {
38         LOGE("Parse from string1 failed![%s]", srcPackInfoJsonStr1.c_str());
39         return false;
40     }
41     if (!srcPackInfo2.ParseFromString(srcPackInfoJsonStr2)) {
42         LOGE("Parse from string2 failed![%s]", srcPackInfoJsonStr2.c_str());
43         return false;
44     }
45     if (!VerifyPackInfos(srcPackInfo1, srcPackInfo2)) {
46         LOGE("VerifyPackInfos failed!");
47         return false;
48     }
49     if (!MergeTwoPackInfos(srcPackInfo1, srcPackInfo2)) {
50         LOGE("MergeTwoPackInfos failed!");
51         return false;
52     }
53     dstPackInfoJsonStr = srcPackInfo1.ToString();
54     return true;
55 }
56 
57 // java : mergePackInfoObj
MergeTwoPackInfos(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2)58 bool PackInfoUtils::MergeTwoPackInfos(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2)
59 {
60     std::unique_ptr<PtJson> modulesObj1;
61     std::unique_ptr<PtJson> modulesObj2;
62     if (!srcPackInfo1.GetModulesObject(modulesObj1) || !srcPackInfo2.GetModulesObject(modulesObj2)) {
63         LOGE("Get module node from srcPackInfo1 or srcPackInfo2 failed!");
64         return false;
65     }
66     if (!modulesObj1->IsArray() || !modulesObj2->IsArray()) {
67         LOGE("Module node is not array!");
68         return false;
69     }
70     for (int32_t i = 0; i < modulesObj2->GetSize(); i++) {
71         if (!modulesObj1->Push(modulesObj2->Get(i))) {
72             LOGE("Push module node failed!");
73             return false;
74         }
75     }
76 
77     std::unique_ptr<PtJson> packagesObj1;
78     std::unique_ptr<PtJson> packagesObj2;
79     if (!srcPackInfo1.GetPackagesObject(packagesObj1) || !srcPackInfo2.GetPackagesObject(packagesObj2)) {
80         LOGE("GetPackagesObject failed!");
81         return false;
82     }
83     if (!packagesObj1->IsArray() || !packagesObj2->IsArray()) {
84         LOGE("Package node is not array!");
85         return false;
86     }
87     for (int32_t i = 0; i < packagesObj2->GetSize(); i++) {
88         if (!packagesObj1->Push(packagesObj2->Get(i))) {
89             LOGE("Push package node failed!");
90             return false;
91         }
92     }
93     return true;
94 }
95 
96 // java : mergeTwoPackInfoByPackagePair
MergeTwoPackInfosByPackagePair(const std::string& srcPackInfoJsonStr1, const std::string& srcPackInfoJsonStr2, const std::map<std::string, std::string>& packagesMap, std::string& dstPackInfoJsonStr)97 bool PackInfoUtils::MergeTwoPackInfosByPackagePair(const std::string& srcPackInfoJsonStr1,
98     const std::string& srcPackInfoJsonStr2, const std::map<std::string, std::string>& packagesMap,
99     std::string& dstPackInfoJsonStr)
100 {
101     PackInfo srcPackInfo1;
102     PackInfo srcPackInfo2;
103     if (!srcPackInfo1.ParseFromString(srcPackInfoJsonStr1)) {
104         LOGE("Parse from string1 failed![%s]", srcPackInfoJsonStr1.c_str());
105         return false;
106     }
107     if (!srcPackInfo2.ParseFromString(srcPackInfoJsonStr2)) {
108         LOGE("Parse from string2 failed![%s]", srcPackInfoJsonStr2.c_str());
109         return false;
110     }
111     if (!VerifyPackInfos(srcPackInfo1, srcPackInfo2)) {
112         LOGE("VerifyPackInfos failed!");
113         return false;
114     }
115     auto iter = packagesMap.begin();
116     while (iter != packagesMap.end()) {
117         std::string packageName = iter->first;
118         std::string moduleName = iter->second;
119         std::string tmpStr = packageName.substr(0, packageName.find_last_of(DOT));
120         if (!MergeTwoPackInfosByPackagePair(srcPackInfo1, srcPackInfo2, tmpStr, moduleName)) {
121             LOGE("MergeTwoPackInfosByPackagePair failed!");
122             return false;
123         }
124         ++iter;
125     }
126     dstPackInfoJsonStr = srcPackInfo1.ToString();
127     return true;
128 }
129 
FindAndMergeModulesByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2, const std::string& moduleName)130 bool PackInfoUtils::FindAndMergeModulesByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2,
131     const std::string& moduleName)
132 {
133     std::unique_ptr<PtJson> modulesObj1;
134     std::unique_ptr<PtJson> modulesObj2;
135     if (!srcPackInfo1.GetModulesObject(modulesObj1) || !srcPackInfo2.GetModulesObject(modulesObj2)) {
136         LOGE("Get module node from srcPackInfo1 or srcPackInfo2 failed!");
137         return false;
138     }
139     if (!modulesObj1->IsArray() || !modulesObj2->IsArray()) {
140         LOGE("Module node is not array!");
141         return false;
142     }
143     bool isFind = false;
144     for (int32_t i = 0; i < modulesObj2->GetSize(); i++) {
145         std::unique_ptr<PtJson> distroObj;
146         if (!srcPackInfo2.GetDistroObject(i, distroObj)) {
147             LOGE("GetDistroObject failed!");
148             return false;
149         }
150         std::string moduleNameInDistroObj;
151         if (!srcPackInfo2.GetModuleNameByDistroObj(distroObj, moduleNameInDistroObj)) {
152             LOGE("GetModuleNameByDistroObj failed!");
153             return false;
154         }
155         if (moduleNameInDistroObj.compare(moduleName) == 0) {
156             if (!modulesObj1->Push(modulesObj2->Get(i))) {
157                 LOGE("Push module node failed!");
158                 return false;
159             }
160             isFind = true;
161             break;
162         }
163     }
164     if (!isFind) {
165         LOGE("Cannot find same moduleName in module node!");
166         return false;
167     }
168     return true;
169 }
170 
FindAndMergePackagesByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2, const std::string& packageName)171 bool PackInfoUtils::FindAndMergePackagesByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2,
172     const std::string& packageName)
173 {
174     std::unique_ptr<PtJson> packagesObj1;
175     std::unique_ptr<PtJson> packagesObj2;
176     if (!srcPackInfo1.GetPackagesObject(packagesObj1) || !srcPackInfo2.GetPackagesObject(packagesObj2)) {
177         LOGE("Get package node from srcPackInfo1 or srcPackInfo2 failed!");
178         return false;
179     }
180     if (!packagesObj1->IsArray() || !packagesObj2->IsArray()) {
181         LOGE("Package node is not array!");
182         return false;
183     }
184     bool isFind = false;
185     for (int32_t i = 0; i < packagesObj2->GetSize(); i++) {
186         std::string packageNameInPackageObj;
187         if (!srcPackInfo2.GetNameByPackageObj(packagesObj2->Get(i), packageNameInPackageObj)) {
188             LOGE("GetNameByPackageObj failed!");
189             return false;
190         }
191         if (packageNameInPackageObj.compare(packageName) == 0) {
192             if (!packagesObj1->Push(packagesObj2->Get(i))) {
193                 LOGE("Push Pacakge node failed!");
194                 return false;
195             }
196             isFind = true;
197             break;
198         }
199     }
200     if (!isFind) {
201         LOGE("Cannot find same packageName in package node!");
202         return false;
203     }
204     return true;
205 }
206 
207 // java : mergeTwoPackInfoObjByPackagePair
MergeTwoPackInfosByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2, const std::string& packageName, const std::string& moduleName)208 bool PackInfoUtils::MergeTwoPackInfosByPackagePair(PackInfo& srcPackInfo1, PackInfo& srcPackInfo2,
209     const std::string& packageName, const std::string& moduleName)
210 {
211     if (!FindAndMergeModulesByPackagePair(srcPackInfo1, srcPackInfo2, moduleName)) {
212         LOGE("FindAndMergeModulesByPackagePair failed!");
213         return false;
214     }
215     if (!FindAndMergePackagesByPackagePair(srcPackInfo1, srcPackInfo2, packageName)) {
216         LOGE("FindAndMergePackagesByPackagePair failed!");
217         return false;
218     }
219     return true;
220 }
221 
222 // java : verifyPackInfo
VerifyPackInfos(const PackInfo& packInfo1, const PackInfo& packInfo2)223 bool PackInfoUtils::VerifyPackInfos(const PackInfo& packInfo1, const PackInfo& packInfo2)
224 {
225     std::unique_ptr<PtJson> appObj1;
226     std::unique_ptr<PtJson> appObj2;
227     if (!const_cast<PackInfo&>(packInfo1).GetAppObject(appObj1) ||
228         !const_cast<PackInfo&>(packInfo2).GetAppObject(appObj2)) {
229         LOGE("GetAppObject failed!");
230         return false;
231     }
232     if (!CheckBundleNameInPackInfo(packInfo1, packInfo2)) {
233         LOGE("CheckBundleNameInPackInfo failed!");
234         return false;
235     }
236     if (!CheckBundleTypeInPackInfo(packInfo1, packInfo2)) {
237         LOGE("CheckBundleTypeInPackInfo failed!");
238         return false;
239     }
240     if (!CheckVersionCodeInPackInfo(packInfo1, packInfo2)) {
241         LOGE("CheckVersionCodeInPackInfo failed!");
242         return false;
243     }
244     return true;
245 }
246 
CheckBundleNameInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)247 bool PackInfoUtils::CheckBundleNameInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)
248 {
249     std::string bundleName1;
250     std::string bundleName2;
251     if (!const_cast<PackInfo&>(packInfo1).GetBundleName(bundleName1)) {
252         LOGE("GetBundleName from packInfo1 failed!");
253         return false;
254     }
255     if (!const_cast<PackInfo&>(packInfo2).GetBundleName(bundleName2)) {
256         LOGE("GetBundleName from packInfo2 failed!");
257         return false;
258     }
259     if (bundleName1.compare(bundleName2) != 0) {
260         LOGE("bundleName is not same");
261         return false;
262     }
263     return true;
264 }
265 
CheckBundleTypeInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)266 bool PackInfoUtils::CheckBundleTypeInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)
267 {
268     std::string bundleType1;
269     std::string bundleType2;
270     if (!const_cast<PackInfo&>(packInfo1).GetBundleType(bundleType1, DEFAULT_BUNDLE_TYPE)) {
271         LOGE("GetBundleType from packInfo1 failed!");
272         return false;
273     }
274     if (!const_cast<PackInfo&>(packInfo2).GetBundleType(bundleType2, DEFAULT_BUNDLE_TYPE)) {
275         LOGE("GetBundleType from packInfo2 failed!");
276         return false;
277     }
278     if (bundleType1.compare(bundleType2) != 0) {
279         LOGE("bundleType is not same");
280         return false;
281     }
282     return true;
283 }
284 
CheckVersionCodeInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)285 bool PackInfoUtils::CheckVersionCodeInPackInfo(const PackInfo& packInfo1, const PackInfo& packInfo2)
286 {
287     PackInfoVersion version1;
288     PackInfoVersion version2;
289     if (!const_cast<PackInfo&>(packInfo1).GetVersion(version1)) {
290         LOGE("GetVersion from packInfo1 failed!");
291         return false;
292     }
293     if (!const_cast<PackInfo&>(packInfo2).GetVersion(version2)) {
294         LOGE("GetVersion from packInfo2 failed!");
295         return false;
296     }
297     if (version1.code != version2.code) {
298         LOGE("Version is not same");
299         return false;
300     }
301     return true;
302 }
303 } // namespace AppPackingTool
304 } // namespace OHOS
305