1 /*
2  * Copyright (C) 2021 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 "json_utils.h"
17 #include <inttypes.h>
18 #include <string.h>
19 #include "securec.h"
20 #include "clib_error.h"
21 #include "hc_types.h"
22 #include "string_util.h"
23 #include "hc_log.h"
24 
25 #define RECURSE_FLAG_TRUE 1
26 #define MAX_DEPTH 10
27 
GetCjsonMaxDepth(const char * jsonStr)28 static int32_t GetCjsonMaxDepth(const char *jsonStr)
29 {
30     int32_t max = 0;
31     uint32_t len = HcStrlen(jsonStr);
32     int32_t cnt = 0;
33     for (uint32_t i = 0; i < len; i++) {
34         if (jsonStr[i] == '{' || jsonStr[i] == '[') {
35             cnt++;
36             if (cnt > max) {
37                 max = cnt;
38             }
39         } else if (jsonStr[i] == '}' || jsonStr[i] == ']') {
40             cnt--;
41         }
42     }
43     return max;
44 }
45 
CreateJsonFromString(const char * jsonStr)46 CJson *CreateJsonFromString(const char *jsonStr)
47 {
48     if (jsonStr == NULL) {
49         return NULL;
50     }
51     int32_t depth = GetCjsonMaxDepth(jsonStr);
52     if (depth > MAX_DEPTH) {
53         LOGE("jsonStr depth %d over 10", depth);
54         return NULL;
55     }
56     return cJSON_Parse(jsonStr);
57 }
58 
CreateJson(void)59 CJson *CreateJson(void)
60 {
61     return cJSON_CreateObject();
62 }
63 
CreateJsonArray(void)64 CJson *CreateJsonArray(void)
65 {
66     return cJSON_CreateArray();
67 }
68 
DuplicateJson(const CJson * jsonObj)69 CJson *DuplicateJson(const CJson *jsonObj)
70 {
71     if (jsonObj == NULL) {
72         return NULL;
73     }
74     return cJSON_Duplicate(jsonObj, RECURSE_FLAG_TRUE);
75 }
76 
FreeJson(CJson * jsonObj)77 void FreeJson(CJson *jsonObj)
78 {
79     cJSON_Delete(jsonObj);
80 }
81 
DeleteItemFromJson(CJson * jsonObj,const char * key)82 void DeleteItemFromJson(CJson *jsonObj, const char *key)
83 {
84     if (jsonObj == NULL || key == NULL) {
85         return;
86     }
87     cJSON_DeleteItemFromObjectCaseSensitive(jsonObj, key);
88 }
89 
DeleteAllItemExceptOne(CJson * jsonObj,const char * key)90 void DeleteAllItemExceptOne(CJson *jsonObj, const char *key)
91 {
92     if (jsonObj == NULL || key == NULL) {
93         return;
94     }
95 
96     CJson *curItem = jsonObj->child;
97     CJson *nextItem = NULL;
98     while (curItem != NULL) {
99         nextItem = curItem->next;
100         if (strcmp(key, curItem->string) != 0) {
101             cJSON_Delete(cJSON_DetachItemViaPointer(jsonObj, curItem));
102         }
103         curItem = nextItem;
104     }
105 }
106 
DeleteAllItem(CJson * jsonObj)107 void DeleteAllItem(CJson *jsonObj)
108 {
109     if (jsonObj == NULL) {
110         return;
111     }
112 
113     CJson *curItem = jsonObj->child;
114     CJson *nextItem = NULL;
115     while (curItem != NULL) {
116         nextItem = curItem->next;
117         cJSON_Delete(cJSON_DetachItemViaPointer(jsonObj, curItem));
118         curItem = nextItem;
119     }
120 }
121 
DetachItemFromJson(CJson * jsonObj,const char * key)122 CJson *DetachItemFromJson(CJson *jsonObj, const char *key)
123 {
124     if (jsonObj == NULL || key == NULL) {
125         return NULL;
126     }
127 
128     return cJSON_DetachItemFromObjectCaseSensitive(jsonObj, key);
129 }
130 
PackJsonToString(const CJson * jsonObj)131 char *PackJsonToString(const CJson *jsonObj)
132 {
133     if (jsonObj == NULL) {
134         return NULL;
135     }
136     return cJSON_PrintUnformatted(jsonObj);
137 }
138 
FreeJsonString(char * jsonStr)139 void FreeJsonString(char *jsonStr)
140 {
141     if (jsonStr != NULL) {
142         cJSON_free(jsonStr);
143     }
144 }
145 
GetItemNum(const CJson * jsonObj)146 int GetItemNum(const CJson *jsonObj)
147 {
148     if (jsonObj == NULL) {
149         return 0;
150     }
151     return cJSON_GetArraySize(jsonObj);
152 }
153 
GetItemKey(const CJson * item)154 const char *GetItemKey(const CJson *item)
155 {
156     if (item == NULL) {
157         return NULL;
158     }
159     return item->string;
160 }
161 
GetObjFromJson(const CJson * jsonObj,const char * key)162 CJson *GetObjFromJson(const CJson *jsonObj, const char *key)
163 {
164     if (jsonObj == NULL || key == NULL) {
165         return NULL;
166     }
167 
168     cJSON *objValue = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
169     if (objValue != NULL) {
170         return objValue;
171     }
172 
173     int len = cJSON_GetArraySize(jsonObj);
174     for (int i = 0; i < len; i++) {
175         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
176         if (cJSON_IsObject(item)) {
177             cJSON *obj = GetObjFromJson(item, key);
178             if (obj != NULL) {
179                 return obj;
180             }
181         }
182     }
183 
184     return NULL;
185 }
186 
GetItemFromArray(const CJson * jsonArr,int index)187 CJson *GetItemFromArray(const CJson *jsonArr, int index)
188 {
189     if (jsonArr == NULL) {
190         return NULL;
191     }
192     return cJSON_GetArrayItem(jsonArr, index);
193 }
194 
GetStringFromJson(const CJson * jsonObj,const char * key)195 const char *GetStringFromJson(const CJson *jsonObj, const char *key)
196 {
197     if (jsonObj == NULL || key == NULL) {
198         return NULL;
199     }
200 
201     cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
202     if (jsonObjTmp != NULL && cJSON_IsString(jsonObjTmp)) {
203         return cJSON_GetStringValue(jsonObjTmp);
204     }
205 
206     int len = cJSON_GetArraySize(jsonObj);
207     for (int i = 0; i < len; i++) {
208         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
209         if (cJSON_IsObject(item)) {
210             const char *resValue = GetStringFromJson(item, key);
211             if (resValue != NULL) {
212                 return resValue;
213             }
214         }
215     }
216 
217     return NULL;
218 }
219 
GetByteLenFromJson(const CJson * jsonObj,const char * key,uint32_t * byteLen)220 int32_t GetByteLenFromJson(const CJson *jsonObj, const char *key, uint32_t *byteLen)
221 {
222     if (jsonObj == NULL || key == NULL || byteLen == NULL) {
223         return CLIB_ERR_NULL_PTR;
224     }
225 
226     const char *valueStr = GetStringFromJson(jsonObj, key);
227     if (valueStr == NULL) {
228         return CLIB_ERR_JSON_GET;
229     }
230     *byteLen = HcStrlen(valueStr) / BYTE_TO_HEX_OPER_LENGTH;
231     return CLIB_SUCCESS;
232 }
233 
GetByteFromJson(const CJson * jsonObj,const char * key,uint8_t * byte,uint32_t len)234 int32_t GetByteFromJson(const CJson *jsonObj, const char *key, uint8_t *byte, uint32_t len)
235 {
236     if (jsonObj == NULL || key == NULL || byte == NULL) {
237         return CLIB_ERR_NULL_PTR;
238     }
239 
240     const char *valueStr = GetStringFromJson(jsonObj, key);
241     if (valueStr == NULL) {
242         return CLIB_ERR_JSON_GET;
243     }
244     if (len < HcStrlen(valueStr) / BYTE_TO_HEX_OPER_LENGTH) {
245         return CLIB_ERR_INVALID_LEN;
246     }
247     return HexStringToByte(valueStr, byte, len);
248 }
249 
GetIntFromJson(const CJson * jsonObj,const char * key,int32_t * value)250 int32_t GetIntFromJson(const CJson *jsonObj, const char *key, int32_t *value)
251 {
252     if (jsonObj == NULL || key == NULL || value == NULL) {
253         return CLIB_ERR_NULL_PTR;
254     }
255 
256     cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
257     if (jsonObjTmp != NULL && cJSON_IsNumber(jsonObjTmp)) {
258         *value = (int)cJSON_GetNumberValue(jsonObjTmp);
259         return CLIB_SUCCESS;
260     }
261 
262     int len = cJSON_GetArraySize(jsonObj);
263     for (int i = 0; i < len; i++) {
264         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
265         if (cJSON_IsObject(item)) {
266             int32_t ret = GetIntFromJson(item, key, value);
267             if (ret == CLIB_SUCCESS) {
268                 return ret;
269             }
270         }
271     }
272 
273     return CLIB_ERR_JSON_GET;
274 }
275 
GetUnsignedIntFromJson(const CJson * jsonObj,const char * key,uint32_t * value)276 int32_t GetUnsignedIntFromJson(const CJson *jsonObj, const char *key, uint32_t *value)
277 {
278     if (jsonObj == NULL || key == NULL || value == NULL) {
279         return CLIB_ERR_NULL_PTR;
280     }
281 
282     cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
283     if (jsonObjTmp != NULL && cJSON_IsNumber(jsonObjTmp)) {
284         double realValue = cJSON_GetNumberValue(jsonObjTmp);
285         if (realValue < 0) {
286             int32_t tmpValue = (int32_t)realValue;
287             *value = (uint32_t)tmpValue;
288         } else {
289             *value = (uint32_t)realValue;
290         }
291         return CLIB_SUCCESS;
292     }
293 
294     int len = cJSON_GetArraySize(jsonObj);
295     for (int i = 0; i < len; i++) {
296         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
297         if (cJSON_IsObject(item)) {
298             int32_t ret = GetUnsignedIntFromJson(item, key, value);
299             if (ret == CLIB_SUCCESS) {
300                 return ret;
301             }
302         }
303     }
304 
305     return CLIB_ERR_JSON_GET;
306 }
307 
GetInt64FromJson(const CJson * jsonObj,const char * key,int64_t * value)308 int32_t GetInt64FromJson(const CJson *jsonObj, const char *key, int64_t *value)
309 {
310     const char *str = GetStringFromJson(jsonObj, key);
311     if (str == NULL) {
312         return CLIB_ERR_JSON_GET;
313     }
314     *value = StringToInt64(str);
315     return CLIB_SUCCESS;
316 }
317 
GetBoolFromJson(const CJson * jsonObj,const char * key,bool * value)318 int32_t GetBoolFromJson(const CJson *jsonObj, const char *key, bool *value)
319 {
320     if (jsonObj == NULL || key == NULL || value == NULL) {
321         return CLIB_ERR_NULL_PTR;
322     }
323 
324     cJSON *jsonObjTmp = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
325     if (jsonObjTmp != NULL && cJSON_IsBool(jsonObjTmp)) {
326         *value = cJSON_IsTrue(jsonObjTmp) ? true : false;
327         return CLIB_SUCCESS;
328     }
329 
330     int len = cJSON_GetArraySize(jsonObj);
331     for (int i = 0; i < len; i++) {
332         cJSON *item = cJSON_GetArrayItem(jsonObj, i);
333         if (cJSON_IsObject(item)) {
334             int32_t ret = GetBoolFromJson(item, key, value);
335             if (ret == CLIB_SUCCESS) {
336                 return ret;
337             }
338         }
339     }
340 
341     return CLIB_ERR_JSON_GET;
342 }
343 
GetStringValue(const CJson * item)344 char *GetStringValue(const CJson *item)
345 {
346     return cJSON_GetStringValue(item);
347 }
348 
AddObjToJson(CJson * jsonObj,const char * key,const CJson * childObj)349 int32_t AddObjToJson(CJson *jsonObj, const char *key, const CJson *childObj)
350 {
351     if (jsonObj == NULL || key == NULL || childObj == NULL) {
352         return CLIB_ERR_NULL_PTR;
353     }
354 
355     cJSON *tmpObj = cJSON_Duplicate(childObj, RECURSE_FLAG_TRUE);
356     if (tmpObj == NULL) {
357         return CLIB_ERR_JSON_DUPLICATE;
358     }
359 
360     cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
361     if (objInJson == NULL) {
362         if (cJSON_AddItemToObject(jsonObj, key, tmpObj) == false) {
363             cJSON_Delete(tmpObj);
364             return CLIB_ERR_JSON_ADD;
365         }
366     } else {
367         if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmpObj) == false) {
368             cJSON_Delete(tmpObj);
369             return CLIB_ERR_JSON_REPLACE;
370         }
371     }
372 
373     return CLIB_SUCCESS;
374 }
375 
AddObjToArray(CJson * jsonArr,CJson * item)376 int32_t AddObjToArray(CJson *jsonArr, CJson *item)
377 {
378     if (jsonArr == NULL || item == NULL) {
379         return CLIB_ERR_NULL_PTR;
380     }
381 
382     if (cJSON_IsArray(jsonArr) == false) {
383         return CLIB_ERR_INVALID_PARAM;
384     }
385 
386     bool ret = cJSON_AddItemToArray(jsonArr, item);
387     if (ret == false) {
388         return CLIB_ERR_JSON_ADD;
389     }
390 
391     return CLIB_SUCCESS;
392 }
393 
AddStringToArray(CJson * jsonArr,const char * string)394 int32_t AddStringToArray(CJson *jsonArr, const char *string)
395 {
396     if (jsonArr == NULL || string == NULL) {
397         return CLIB_ERR_NULL_PTR;
398     }
399 
400     if (cJSON_IsArray(jsonArr) == false) {
401         return CLIB_ERR_INVALID_PARAM;
402     }
403 
404     cJSON *strObj = cJSON_CreateString(string);
405     if (strObj == NULL) {
406         return CLIB_ERR_BAD_ALLOC;
407     }
408     bool ret = cJSON_AddItemToArray(jsonArr, strObj);
409     if (ret == false) {
410         cJSON_Delete(strObj);
411         return CLIB_ERR_JSON_ADD;
412     }
413 
414     return CLIB_SUCCESS;
415 }
416 
AddStringToJson(CJson * jsonObj,const char * key,const char * value)417 int32_t AddStringToJson(CJson *jsonObj, const char *key, const char *value)
418 {
419     if (jsonObj == NULL || key == NULL || value == NULL) {
420         return CLIB_ERR_NULL_PTR;
421     }
422 
423     cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
424     if (objInJson == NULL) {
425         if (cJSON_AddStringToObject(jsonObj, key, value) == NULL) {
426             return CLIB_ERR_JSON_GET;
427         }
428     } else {
429         cJSON *tmp = cJSON_CreateString(value);
430         if (tmp == NULL) {
431             return CLIB_ERR_BAD_ALLOC;
432         }
433         if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) {
434             cJSON_Delete(tmp);
435             return CLIB_ERR_JSON_REPLACE;
436         }
437     }
438 
439     return CLIB_SUCCESS;
440 }
441 
AddByteToJson(CJson * jsonObj,const char * key,const uint8_t * byte,uint32_t len)442 int32_t AddByteToJson(CJson *jsonObj, const char *key, const uint8_t *byte, uint32_t len)
443 {
444     if (jsonObj == NULL || key == NULL || byte == NULL) {
445         return CLIB_ERR_NULL_PTR;
446     }
447 
448     uint32_t hexLen = len * BYTE_TO_HEX_OPER_LENGTH + 1;
449     char *hexStr = (char *)HcMalloc(hexLen, 0);
450     if (hexStr == NULL) {
451         return CLIB_ERR_BAD_ALLOC;
452     }
453     int32_t ret = ByteToHexString(byte, len, hexStr, hexLen);
454     if (ret != CLIB_SUCCESS) {
455         HcFree(hexStr);
456         return ret;
457     }
458 
459     ret = AddStringToJson(jsonObj, key, hexStr);
460     if (ret != CLIB_SUCCESS) {
461         HcFree(hexStr);
462         return ret;
463     }
464 
465     HcFree(hexStr);
466     return CLIB_SUCCESS;
467 }
468 
AddBoolToJson(CJson * jsonObj,const char * key,bool value)469 int32_t AddBoolToJson(CJson *jsonObj, const char *key, bool value)
470 {
471     if (jsonObj == NULL || key == NULL) {
472         return CLIB_ERR_NULL_PTR;
473     }
474 
475     cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
476     if (objInJson == NULL) {
477         if (cJSON_AddBoolToObject(jsonObj, key, value) == NULL) {
478             return CLIB_ERR_JSON_GET;
479         }
480     } else {
481         cJSON *tmp = cJSON_CreateBool(value);
482         if (tmp == NULL) {
483             return CLIB_ERR_BAD_ALLOC;
484         }
485         if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) {
486             cJSON_Delete(tmp);
487             return CLIB_ERR_JSON_REPLACE;
488         }
489     }
490 
491     return CLIB_SUCCESS;
492 }
493 
AddIntToJson(CJson * jsonObj,const char * key,int value)494 int32_t AddIntToJson(CJson *jsonObj, const char *key, int value)
495 {
496     if (jsonObj == NULL || key == NULL) {
497         return CLIB_ERR_NULL_PTR;
498     }
499 
500     cJSON *objInJson = cJSON_GetObjectItemCaseSensitive(jsonObj, key);
501     if (objInJson == NULL) {
502         if (cJSON_AddNumberToObject(jsonObj, key, value) == NULL) {
503             return CLIB_ERR_JSON_GET;
504         }
505     } else {
506         cJSON *tmp = cJSON_CreateNumber(value);
507         if (tmp == NULL) {
508             return CLIB_ERR_BAD_ALLOC;
509         }
510         if (cJSON_ReplaceItemInObjectCaseSensitive(jsonObj, key, tmp) == false) {
511             cJSON_Delete(tmp);
512             return CLIB_ERR_JSON_REPLACE;
513         }
514     }
515 
516     return CLIB_SUCCESS;
517 }
518 
AddInt64StringToJson(CJson * jsonObj,const char * key,int64_t value)519 int32_t AddInt64StringToJson(CJson *jsonObj, const char *key, int64_t value)
520 {
521     char buffer[65] = { 0 };
522     if (sprintf_s(buffer, sizeof(buffer), "%" PRId64, value) <= 0) {
523         return CLIB_FAILED;
524     }
525     if (AddStringToJson(jsonObj, key, buffer) != CLIB_SUCCESS) {
526         return CLIB_ERR_JSON_ADD;
527     }
528     return CLIB_SUCCESS;
529 }
530 
AddStringArrayToJson(CJson * jsonObj,const char * key,const char * const * stringArray,uint32_t arrayLen)531 int32_t AddStringArrayToJson(CJson *jsonObj, const char *key, const char * const *stringArray, uint32_t arrayLen)
532 {
533     if (jsonObj == NULL || key == NULL || stringArray == NULL) {
534         return CLIB_ERR_NULL_PTR;
535     }
536 
537     cJSON *strArrayObj = cJSON_CreateStringArray(stringArray, arrayLen);
538     if (strArrayObj == NULL) {
539         return CLIB_ERR_BAD_ALLOC;
540     }
541     if (cJSON_AddItemToObject(jsonObj, key, strArrayObj) == false) {
542         cJSON_Delete(strArrayObj);
543         return CLIB_ERR_JSON_ADD;
544     }
545     return CLIB_SUCCESS;
546 }
547 
ClearSensitiveStringInJson(CJson * jsonObj,const char * key)548 void ClearSensitiveStringInJson(CJson *jsonObj, const char *key)
549 {
550     if (jsonObj == NULL || key == NULL) {
551         return;
552     }
553     char *str = (char *)GetStringFromJson(jsonObj, key);
554     if (str == NULL) {
555         return;
556     }
557     (void)memset_s(str, HcStrlen(str), 0, HcStrlen(str));
558 }
559 
ClearAndFreeJsonString(char * jsonStr)560 void ClearAndFreeJsonString(char *jsonStr)
561 {
562     if (jsonStr == NULL) {
563         return;
564     }
565     (void)memset_s(jsonStr, HcStrlen(jsonStr), 0, HcStrlen(jsonStr));
566     FreeJsonString(jsonStr);
567 }
568