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