1 /*
2 * Copyright (C) 2025 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 "cjson_utils.h"
17 #include <cstdint>
18 #include <memory>
19 #include <string>
20
21 namespace OHOS {
22 namespace Security {
23 namespace AccessToken {
24 namespace {
25 #define RECURSE_FLAG_TRUE 1
26 #define PRINT_FORMAT_LEVEL_MAX 500
27 }
28
GetItemFromArray(const CJson * jsonArr,int32_t index)29 CJson* GetItemFromArray(const CJson* jsonArr, int32_t index)
30 {
31 if (jsonArr == nullptr) {
32 return nullptr;
33 }
34 return cJSON_GetArrayItem(jsonArr, index);
35 }
36
CreateJsonFromString(const std::string & jsonStr)37 CJsonUnique CreateJsonFromString(const std::string& jsonStr)
38 {
39 if (jsonStr.empty()) {
40 return nullptr;
41 }
42 CJsonUnique aPtr(cJSON_Parse(jsonStr.c_str()), FreeJson);
43 return aPtr;
44 }
45
CreateJson(void)46 CJsonUnique CreateJson(void)
47 {
48 CJsonUnique aPtr(cJSON_CreateObject(), FreeJson);
49 return aPtr;
50 }
51
CreateJsonArray(void)52 CJsonUnique CreateJsonArray(void)
53 {
54 CJsonUnique aPtr(cJSON_CreateArray(), FreeJson);
55 return aPtr;
56 }
57
CreateJsonString(const std::string & value)58 CJsonUnique CreateJsonString(const std::string& value)
59 {
60 CJsonUnique aPtr(cJSON_CreateString(value.c_str()), FreeJson);
61 return aPtr;
62 }
63
FreeJson(CJson * jsonObj)64 void FreeJson(CJson* jsonObj)
65 {
66 cJSON_Delete(jsonObj);
67 jsonObj = nullptr;
68 }
69
PackJsonToString(const CJson * jsonObj)70 std::string PackJsonToString(const CJson* jsonObj)
71 {
72 char* ptr = cJSON_PrintUnformatted(jsonObj);
73 if (ptr == nullptr) {
74 return std::string();
75 }
76 std::string ret = std::string(ptr);
77 FreeJsonString(ptr);
78 return ret;
79 }
80
PackJsonToString(const CJsonUnique & jsonObj)81 std::string PackJsonToString(const CJsonUnique& jsonObj)
82 {
83 return PackJsonToString(jsonObj.get());
84 }
85
GetTabContentString(uint32_t level)86 static std::string GetTabContentString(uint32_t level)
87 {
88 std::string str = "";
89 for (uint32_t i = 0; i < level; ++i) {
90 str += " ";
91 }
92 return str;
93 }
94
JsonToStringFormatted(const CJson * jsonObj,uint32_t level)95 std::string JsonToStringFormatted(const CJson* jsonObj, uint32_t level)
96 {
97 if (jsonObj == nullptr || level > PRINT_FORMAT_LEVEL_MAX) {
98 return "";
99 }
100 std::string str = "";
101 CJson* child = nullptr;
102 switch (jsonObj->type) {
103 case cJSON_Object:
104 str += GetTabContentString(level) + "{\n";
105 child = jsonObj->child;
106 while (child != nullptr) {
107 str += GetTabContentString(level + 2) + "\"" + std::string(child->string) + "\": "; // 2: space
108 str += JsonToStringFormatted(child, level + 2); // 2: space
109 str += (child->next != nullptr) ? ",\n" : "\n";
110 child = child->next;
111 }
112 str += GetTabContentString(level) + "}";
113 break;
114 case cJSON_Array:
115 str += "[\n";
116 child = jsonObj->child;
117 while (child != nullptr) {
118 str += JsonToStringFormatted(child, level + 2); // 2: space
119 str += (child->next != nullptr) ? ",\n" : "\n";
120 child = child->next;
121 }
122 str += GetTabContentString(level) + "]";
123 break;
124 case cJSON_String:
125 str += "\"" + std::string(jsonObj->valuestring) + "\"";
126 break;
127 case cJSON_Number:
128 str += std::to_string(static_cast<int64_t>(jsonObj->valuedouble));
129 break;
130 case cJSON_True:
131 str += "true";
132 break;
133 case cJSON_False:
134 str += "false";
135 break;
136 default:
137 str += "unkown type";
138 break;
139 }
140 return str;
141 }
142
FreeJsonString(char * jsonStr)143 void FreeJsonString(char* jsonStr)
144 {
145 if (jsonStr != nullptr) {
146 cJSON_free(jsonStr);
147 }
148 }
149
GetObjFromJson(const CJson * jsonObj,const std::string & key)150 CJson* GetObjFromJson(const CJson* jsonObj, const std::string& key)
151 {
152 if ((jsonObj == nullptr) || key.empty()) {
153 return nullptr;
154 }
155
156 CJson* objValue = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
157 if (objValue != nullptr && cJSON_IsObject(objValue)) {
158 return objValue;
159 }
160 return nullptr;
161 }
162
GetObjFromJson(CJsonUnique & jsonObj,const std::string & key)163 CJson* GetObjFromJson(CJsonUnique& jsonObj, const std::string& key)
164 {
165 return GetObjFromJson(jsonObj.get(), key);
166 }
167
GetArrayFromJson(const CJson * jsonObj,const std::string & key)168 CJson* GetArrayFromJson(const CJson* jsonObj, const std::string& key)
169 {
170 if ((jsonObj == nullptr) || key.empty()) {
171 return nullptr;
172 }
173
174 CJson* objValue = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
175 if (objValue != nullptr && cJSON_IsArray(objValue)) {
176 return objValue;
177 }
178 return nullptr;
179 }
180
GetArrayFromJson(CJsonUnique & jsonObj,const std::string & key)181 CJson* GetArrayFromJson(CJsonUnique& jsonObj, const std::string& key)
182 {
183 return GetArrayFromJson(jsonObj.get(), key);
184 }
185
GetArrayFromJson(const CJson * jsonObj,const std::string & key,std::vector<std::string> & out)186 bool GetArrayFromJson(const CJson* jsonObj, const std::string& key, std::vector<std::string>& out)
187 {
188 if (jsonObj == nullptr || key.empty()) {
189 return false;
190 }
191
192 cJSON* stringArray = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
193 if (stringArray != nullptr && cJSON_IsArray(stringArray)) {
194 int32_t arraySize = cJSON_GetArraySize(stringArray);
195 for (int32_t i = 0; i < arraySize; i++) {
196 CJson* stringItem = cJSON_GetArrayItem(stringArray, i);
197 if (stringItem != nullptr && cJSON_IsString(stringItem)) {
198 out.emplace_back(cJSON_GetStringValue(stringItem));
199 }
200 }
201 return true;
202 }
203 return false;
204 }
205
GetStringFromJson(const CJson * jsonObj,const std::string & key,std::string & out)206 bool GetStringFromJson(const CJson* jsonObj, const std::string& key, std::string& out)
207 {
208 if (jsonObj == nullptr || key.empty()) {
209 return false;
210 }
211
212 cJSON* jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
213 if (jsonObjTmp != nullptr && cJSON_IsString(jsonObjTmp)) {
214 out = cJSON_GetStringValue(jsonObjTmp);
215 return true;
216 }
217 return false;
218 }
219
GetIntFromJson(const CJson * jsonObj,const std::string & key,int32_t & value)220 bool GetIntFromJson(const CJson* jsonObj, const std::string& key, int32_t& value)
221 {
222 if ((jsonObj == nullptr) || key.empty()) {
223 return false;
224 }
225
226 CJson* jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
227 if (jsonObjTmp != nullptr && cJSON_IsNumber(jsonObjTmp)) {
228 value = static_cast<int>(cJSON_GetNumberValue(jsonObjTmp));
229 return true;
230 }
231 return false;
232 }
233
GetIntFromJson(const CJsonUnique & jsonObj,const std::string & key,int32_t & value)234 bool GetIntFromJson(const CJsonUnique& jsonObj, const std::string& key, int32_t& value)
235 {
236 return GetIntFromJson(jsonObj.get(), key, value);
237 }
238
GetUnsignedIntFromJson(const CJson * jsonObj,const std::string & key,uint32_t & value)239 bool GetUnsignedIntFromJson(const CJson* jsonObj, const std::string& key, uint32_t& value)
240 {
241 if ((jsonObj == nullptr) || key.empty()) {
242 return false;
243 }
244
245 CJson* jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
246 if (jsonObjTmp != nullptr && cJSON_IsNumber(jsonObjTmp)) {
247 value = static_cast<uint32_t>(cJSON_GetNumberValue(jsonObjTmp));
248 return true;
249 }
250 return false;
251 }
252
GetUnsignedIntFromJson(const CJsonUnique & jsonObj,const std::string & key,uint32_t & value)253 bool GetUnsignedIntFromJson(const CJsonUnique& jsonObj, const std::string& key, uint32_t& value)
254 {
255 return GetUnsignedIntFromJson(jsonObj.get(), key, value);
256 }
257
GetBoolFromJson(const CJson * jsonObj,const std::string & key,bool & value)258 bool GetBoolFromJson(const CJson* jsonObj, const std::string& key, bool& value)
259 {
260 if ((jsonObj == nullptr) || key.empty()) {
261 return false;
262 }
263
264 CJson* jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
265 if (jsonObjTmp != nullptr && cJSON_IsBool(jsonObjTmp)) {
266 value = cJSON_IsTrue(jsonObjTmp) ? true : false;
267 return true;
268 }
269 return false;
270 }
271
GetBoolFromJson(const CJsonUnique & jsonObj,const std::string & key,bool & value)272 bool GetBoolFromJson(const CJsonUnique& jsonObj, const std::string& key, bool& value)
273 {
274 return GetBoolFromJson(jsonObj.get(), key, value);
275 }
276
AddObjToJson(CJson * jsonObj,const std::string & key,const CJson * childObj)277 bool AddObjToJson(CJson* jsonObj, const std::string& key, const CJson* childObj)
278 {
279 if ((jsonObj == nullptr) || key.empty() || (childObj == nullptr)) {
280 return false;
281 }
282
283 CJson* tmpObj = cJSON_Duplicate(childObj, RECURSE_FLAG_TRUE);
284 if (tmpObj == nullptr) {
285 return false;
286 }
287
288 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
289 if (objInJson == nullptr) {
290 if (!cJSON_AddItemToObject(jsonObj, key.c_str(), tmpObj)) {
291 cJSON_Delete(tmpObj);
292 return false;
293 }
294 } else {
295 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmpObj)) {
296 cJSON_Delete(tmpObj);
297 return false;
298 }
299 }
300 return true;
301 }
302
AddObjToJson(CJsonUnique & jsonObj,const std::string & key,CJsonUnique & childObj)303 bool AddObjToJson(CJsonUnique& jsonObj, const std::string& key, CJsonUnique& childObj)
304 {
305 return AddObjToJson(jsonObj.get(), key, childObj.get());
306 }
307
AddObjToArray(CJson * jsonArr,CJson * item)308 bool AddObjToArray(CJson* jsonArr, CJson* item)
309 {
310 if ((jsonArr == nullptr) || (item == nullptr)) {
311 return false;
312 }
313
314 if (!cJSON_IsArray(jsonArr)) {
315 return false;
316 }
317
318 CJson* tmpObj = cJSON_Duplicate(item, RECURSE_FLAG_TRUE);
319 if (tmpObj == nullptr) {
320 return false;
321 }
322 return cJSON_AddItemToArray(jsonArr, tmpObj);
323 }
324
AddObjToArray(CJsonUnique & jsonArr,CJsonUnique & item)325 bool AddObjToArray(CJsonUnique& jsonArr, CJsonUnique& item)
326 {
327 return AddObjToArray(jsonArr.get(), item.get());
328 }
329
AddStringToJson(CJson * jsonObj,const std::string & key,const std::string & value)330 bool AddStringToJson(CJson* jsonObj, const std::string& key, const std::string& value)
331 {
332 if ((jsonObj == nullptr) || key.empty() || value.empty()) {
333 return false;
334 }
335
336 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
337 if (objInJson == nullptr) {
338 if (cJSON_AddStringToObject(jsonObj, key.c_str(), value.c_str()) == nullptr) {
339 return false;
340 }
341 } else {
342 CJson* tmp = cJSON_CreateString(value.c_str());
343 if (tmp == nullptr) {
344 return false;
345 }
346 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmp)) {
347 cJSON_Delete(tmp);
348 return false;
349 }
350 }
351
352 return true;
353 }
354
AddStringToJson(CJsonUnique & jsonObj,const std::string & key,const std::string & value)355 bool AddStringToJson(CJsonUnique& jsonObj, const std::string& key, const std::string& value)
356 {
357 return AddStringToJson(jsonObj.get(), key, value);
358 }
359
AddBoolToJson(CJson * jsonObj,const std::string & key,bool value)360 bool AddBoolToJson(CJson* jsonObj, const std::string& key, bool value)
361 {
362 if ((jsonObj == nullptr) || key.empty()) {
363 return false;
364 }
365
366 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
367 if (objInJson == nullptr) {
368 if (cJSON_AddBoolToObject(jsonObj, key.c_str(), value) == nullptr) {
369 return false;
370 }
371 } else {
372 CJson* tmp = cJSON_CreateBool(value);
373 if (tmp == nullptr) {
374 return false;
375 }
376 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmp)) {
377 cJSON_Delete(tmp);
378 return false;
379 }
380 }
381
382 return true;
383 }
384
AddBoolToJson(CJsonUnique & jsonObj,const std::string & key,bool value)385 bool AddBoolToJson(CJsonUnique& jsonObj, const std::string& key, bool value)
386 {
387 return AddBoolToJson(jsonObj.get(), key, value);
388 }
389
AddIntToJson(CJson * jsonObj,const std::string & key,const int32_t value)390 bool AddIntToJson(CJson* jsonObj, const std::string& key, const int32_t value)
391 {
392 if ((jsonObj == nullptr) || key.empty()) {
393 return false;
394 }
395
396 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
397 if (objInJson == nullptr) {
398 if (cJSON_AddNumberToObject(jsonObj, key.c_str(), value) == nullptr) {
399 return false;
400 }
401 } else {
402 CJson* tmp = cJSON_CreateNumber(value);
403 if (tmp == nullptr) {
404 return false;
405 }
406 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmp)) {
407 cJSON_Delete(tmp);
408 return false;
409 }
410 }
411
412 return true;
413 }
414
AddIntToJson(CJsonUnique & jsonObj,const std::string & key,int32_t value)415 bool AddIntToJson(CJsonUnique& jsonObj, const std::string& key, int32_t value)
416 {
417 return AddIntToJson(jsonObj.get(), key, value);
418 }
419
AddUnsignedIntToJson(CJson * jsonObj,const std::string & key,const uint32_t value)420 bool AddUnsignedIntToJson(CJson* jsonObj, const std::string& key, const uint32_t value)
421 {
422 if ((jsonObj == nullptr) || key.empty()) {
423 return false;
424 }
425
426 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
427 double tmpValue = static_cast<double>(value);
428 if (objInJson == nullptr) {
429 if (cJSON_AddNumberToObject(jsonObj, key.c_str(), tmpValue) == nullptr) {
430 return false;
431 }
432 } else {
433 CJson* tmp = cJSON_CreateNumber(tmpValue);
434 if (tmp == nullptr) {
435 return false;
436 }
437 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmp)) {
438 cJSON_Delete(tmp);
439 return false;
440 }
441 }
442 return true;
443 }
444
AddUnsignedIntToJson(CJsonUnique & jsonObj,const std::string & key,uint32_t value)445 bool AddUnsignedIntToJson(CJsonUnique& jsonObj, const std::string& key, uint32_t value)
446 {
447 return AddUnsignedIntToJson(jsonObj.get(), key, value);
448 }
449
AddInt64ToJson(CJson * jsonObj,const std::string & key,int64_t value)450 bool AddInt64ToJson(CJson* jsonObj, const std::string& key, int64_t value)
451 {
452 if ((jsonObj == nullptr) || key.empty()) {
453 return false;
454 }
455
456 CJson* objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
457 double tmpValue = static_cast<double>(value);
458 if (objInJson == nullptr) {
459 if (cJSON_AddNumberToObject(jsonObj, key.c_str(), tmpValue) == nullptr) {
460 return false;
461 }
462 } else {
463 CJson* tmp = cJSON_CreateNumber(tmpValue);
464 if (tmp == nullptr) {
465 return false;
466 }
467 if (!cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key.c_str(), tmp)) {
468 cJSON_Delete(tmp);
469 return false;
470 }
471 }
472 return true;
473 }
474
AddInt64ToJson(CJsonUnique & jsonObj,const std::string & key,int64_t value)475 bool AddInt64ToJson(CJsonUnique& jsonObj, const std::string& key, int64_t value)
476 {
477 return AddInt64ToJson(jsonObj.get(), key, value);
478 }
479 } // namespace AccessToken
480 } // namespace Security
481 } // namespace OHOS