]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_json.c
b9e4a743490d78548fa4fd509f2c81245cebea6d
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_json.c
1 /******************************************************************************
2 * ventoy_json.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/dl.h>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
34 #include <grub/net.h>
35 #include <grub/time.h>
36 #include <grub/ventoy.h>
37 #include "ventoy_def.h"
38
39 GRUB_MOD_LICENSE ("GPLv3+");
40
41 static void json_debug(const char *fmt, ...)
42 {
43 va_list args;
44
45 if (g_ventoy_debug == 0)
46 {
47 return;
48 }
49
50 va_start (args, fmt);
51 grub_vprintf (fmt, args);
52 va_end (args);
53
54 grub_printf("\n");
55 }
56
57 static void vtoy_json_free(VTOY_JSON *pstJsonHead)
58 {
59 VTOY_JSON *pstNext = NULL;
60
61 while (NULL != pstJsonHead)
62 {
63 pstNext = pstJsonHead->pstNext;
64 if ((pstJsonHead->enDataType < JSON_TYPE_BUTT) && (NULL != pstJsonHead->pstChild))
65 {
66 vtoy_json_free(pstJsonHead->pstChild);
67 }
68
69 grub_free(pstJsonHead);
70 pstJsonHead = pstNext;
71 }
72
73 return;
74 }
75
76 static char *vtoy_json_skip(const char *pcData)
77 {
78 while ((NULL != pcData) && ('\0' != *pcData) && (*pcData <= 32))
79 {
80 pcData++;
81 }
82
83 return (char *)pcData;
84 }
85
86 VTOY_JSON *vtoy_json_find_item
87 (
88 VTOY_JSON *pstJson,
89 JSON_TYPE enDataType,
90 const char *szKey
91 )
92 {
93 while (NULL != pstJson)
94 {
95 if ((enDataType == pstJson->enDataType) &&
96 (0 == grub_strcmp(szKey, pstJson->pcName)))
97 {
98 return pstJson;
99 }
100 pstJson = pstJson->pstNext;
101 }
102
103 return NULL;
104 }
105
106 static int vtoy_json_parse_number
107 (
108 VTOY_JSON *pstJson,
109 const char *pcData,
110 const char **ppcEnd
111 )
112 {
113 unsigned long Value;
114
115 Value = grub_strtoul(pcData, (char **)ppcEnd, 10);
116 if (*ppcEnd == pcData)
117 {
118 json_debug("Failed to parse json number %s.", pcData);
119 return JSON_FAILED;
120 }
121
122 pstJson->enDataType = JSON_TYPE_NUMBER;
123 pstJson->unData.lValue = Value;
124
125 return JSON_SUCCESS;
126 }
127
128 static int vtoy_json_parse_string
129 (
130 char *pcNewStart,
131 char *pcRawStart,
132 VTOY_JSON *pstJson,
133 const char *pcData,
134 const char **ppcEnd
135 )
136 {
137 grub_uint32_t uiLen = 0;
138 const char *pcPos = NULL;
139 const char *pcTmp = pcData + 1;
140
141 *ppcEnd = pcData;
142
143 if ('\"' != *pcData)
144 {
145 return JSON_FAILED;
146 }
147
148 pcPos = grub_strchr(pcTmp, '\"');
149 if ((NULL == pcPos) || (pcPos < pcTmp))
150 {
151 json_debug("Invalid string %s.", pcData);
152 return JSON_FAILED;
153 }
154
155 *ppcEnd = pcPos + 1;
156 uiLen = (grub_uint32_t)(unsigned long)(pcPos - pcTmp);
157
158 pstJson->enDataType = JSON_TYPE_STRING;
159 pstJson->unData.pcStrVal = pcNewStart + (pcTmp - pcRawStart);
160 pstJson->unData.pcStrVal[uiLen] = '\0';
161
162 return JSON_SUCCESS;
163 }
164
165 static int vtoy_json_parse_array
166 (
167 char *pcNewStart,
168 char *pcRawStart,
169 VTOY_JSON *pstJson,
170 const char *pcData,
171 const char **ppcEnd
172 )
173 {
174 int Ret = JSON_SUCCESS;
175 VTOY_JSON *pstJsonChild = NULL;
176 VTOY_JSON *pstJsonItem = NULL;
177 const char *pcTmp = pcData + 1;
178
179 *ppcEnd = pcData;
180 pstJson->enDataType = JSON_TYPE_ARRAY;
181
182 if ('[' != *pcData)
183 {
184 return JSON_FAILED;
185 }
186
187 pcTmp = vtoy_json_skip(pcTmp);
188
189 if (']' == *pcTmp)
190 {
191 *ppcEnd = pcTmp + 1;
192 return JSON_SUCCESS;
193 }
194
195 JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
196
197 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
198 if (JSON_SUCCESS != Ret)
199 {
200 json_debug("Failed to parse array child.");
201 return JSON_FAILED;
202 }
203
204 pstJsonChild = pstJson->pstChild;
205 pcTmp = vtoy_json_skip(*ppcEnd);
206 while ((NULL != pcTmp) && (',' == *pcTmp))
207 {
208 JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
209 pstJsonChild->pstNext = pstJsonItem;
210 pstJsonItem->pstPrev = pstJsonChild;
211 pstJsonChild = pstJsonItem;
212
213 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
214 if (JSON_SUCCESS != Ret)
215 {
216 json_debug("Failed to parse array child.");
217 return JSON_FAILED;
218 }
219 pcTmp = vtoy_json_skip(*ppcEnd);
220 }
221
222 if ((NULL != pcTmp) && (']' == *pcTmp))
223 {
224 *ppcEnd = pcTmp + 1;
225 return JSON_SUCCESS;
226 }
227 else
228 {
229 *ppcEnd = pcTmp;
230 return JSON_FAILED;
231 }
232 }
233
234 static int vtoy_json_parse_object
235 (
236 char *pcNewStart,
237 char *pcRawStart,
238 VTOY_JSON *pstJson,
239 const char *pcData,
240 const char **ppcEnd
241 )
242 {
243 int Ret = JSON_SUCCESS;
244 VTOY_JSON *pstJsonChild = NULL;
245 VTOY_JSON *pstJsonItem = NULL;
246 const char *pcTmp = pcData + 1;
247
248 *ppcEnd = pcData;
249 pstJson->enDataType = JSON_TYPE_OBJECT;
250
251 if ('{' != *pcData)
252 {
253 return JSON_FAILED;
254 }
255
256 pcTmp = vtoy_json_skip(pcTmp);
257 if ('}' == *pcTmp)
258 {
259 *ppcEnd = pcTmp + 1;
260 return JSON_SUCCESS;
261 }
262
263 JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
264
265 Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
266 if (JSON_SUCCESS != Ret)
267 {
268 json_debug("Failed to parse array child.");
269 return JSON_FAILED;
270 }
271
272 pstJsonChild = pstJson->pstChild;
273 pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
274 pstJsonChild->unData.pcStrVal = NULL;
275
276 pcTmp = vtoy_json_skip(*ppcEnd);
277 if ((NULL == pcTmp) || (':' != *pcTmp))
278 {
279 *ppcEnd = pcTmp;
280 return JSON_FAILED;
281 }
282
283 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
284 if (JSON_SUCCESS != Ret)
285 {
286 json_debug("Failed to parse array child.");
287 return JSON_FAILED;
288 }
289
290 pcTmp = vtoy_json_skip(*ppcEnd);
291 while ((NULL != pcTmp) && (',' == *pcTmp))
292 {
293 JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
294 pstJsonChild->pstNext = pstJsonItem;
295 pstJsonItem->pstPrev = pstJsonChild;
296 pstJsonChild = pstJsonItem;
297
298 Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
299 if (JSON_SUCCESS != Ret)
300 {
301 json_debug("Failed to parse array child.");
302 return JSON_FAILED;
303 }
304
305 pcTmp = vtoy_json_skip(*ppcEnd);
306 pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
307 pstJsonChild->unData.pcStrVal = NULL;
308 if ((NULL == pcTmp) || (':' != *pcTmp))
309 {
310 *ppcEnd = pcTmp;
311 return JSON_FAILED;
312 }
313
314 Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
315 if (JSON_SUCCESS != Ret)
316 {
317 json_debug("Failed to parse array child.");
318 return JSON_FAILED;
319 }
320
321 pcTmp = vtoy_json_skip(*ppcEnd);
322 }
323
324 if ((NULL != pcTmp) && ('}' == *pcTmp))
325 {
326 *ppcEnd = pcTmp + 1;
327 return JSON_SUCCESS;
328 }
329 else
330 {
331 *ppcEnd = pcTmp;
332 return JSON_FAILED;
333 }
334 }
335
336 int vtoy_json_parse_value
337 (
338 char *pcNewStart,
339 char *pcRawStart,
340 VTOY_JSON *pstJson,
341 const char *pcData,
342 const char **ppcEnd
343 )
344 {
345 pcData = vtoy_json_skip(pcData);
346
347 switch (*pcData)
348 {
349 case 'n':
350 {
351 if (0 == grub_strncmp(pcData, "null", 4))
352 {
353 pstJson->enDataType = JSON_TYPE_NULL;
354 *ppcEnd = pcData + 4;
355 return JSON_SUCCESS;
356 }
357 break;
358 }
359 case 'f':
360 {
361 if (0 == grub_strncmp(pcData, "false", 5))
362 {
363 pstJson->enDataType = JSON_TYPE_BOOL;
364 pstJson->unData.lValue = 0;
365 *ppcEnd = pcData + 5;
366 return JSON_SUCCESS;
367 }
368 break;
369 }
370 case 't':
371 {
372 if (0 == grub_strncmp(pcData, "true", 4))
373 {
374 pstJson->enDataType = JSON_TYPE_BOOL;
375 pstJson->unData.lValue = 1;
376 *ppcEnd = pcData + 4;
377 return JSON_SUCCESS;
378 }
379 break;
380 }
381 case '\"':
382 {
383 return vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
384 }
385 case '[':
386 {
387 return vtoy_json_parse_array(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
388 }
389 case '{':
390 {
391 return vtoy_json_parse_object(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
392 }
393 case '-':
394 {
395 return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
396 }
397 default :
398 {
399 if (*pcData >= '0' && *pcData <= '9')
400 {
401 return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
402 }
403 }
404 }
405
406 *ppcEnd = pcData;
407 json_debug("Invalid json data %u.", (grub_uint8_t)(*pcData));
408 return JSON_FAILED;
409 }
410
411 VTOY_JSON * vtoy_json_create(void)
412 {
413 VTOY_JSON *pstJson = NULL;
414
415 pstJson = (VTOY_JSON *)grub_zalloc(sizeof(VTOY_JSON));
416 if (NULL == pstJson)
417 {
418 return NULL;
419 }
420
421 return pstJson;
422 }
423
424 int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData)
425 {
426 grub_uint32_t uiMemSize = 0;
427 int Ret = JSON_SUCCESS;
428 char *pcNewBuf = NULL;
429 const char *pcEnd = NULL;
430
431 uiMemSize = grub_strlen(szJsonData) + 1;
432 pcNewBuf = (char *)grub_malloc(uiMemSize);
433 if (NULL == pcNewBuf)
434 {
435 json_debug("Failed to alloc new buf.");
436 return JSON_FAILED;
437 }
438 grub_memcpy(pcNewBuf, szJsonData, uiMemSize);
439 pcNewBuf[uiMemSize - 1] = 0;
440
441 Ret = vtoy_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd);
442 if (JSON_SUCCESS != Ret)
443 {
444 json_debug("Failed to parse json data %s start=%p, end=%p:%s.",
445 szJsonData, szJsonData, pcEnd, pcEnd);
446 return JSON_FAILED;
447 }
448
449 return JSON_SUCCESS;
450 }
451
452 int vtoy_json_scan_parse
453 (
454 const VTOY_JSON *pstJson,
455 grub_uint32_t uiParseNum,
456 JSON_PARSE *pstJsonParse
457 )
458 {
459 grub_uint32_t i = 0;
460 const VTOY_JSON *pstJsonCur = NULL;
461 JSON_PARSE *pstCurParse = NULL;
462
463 for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext)
464 {
465 if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) ||
466 (JSON_TYPE_ARRAY == pstJsonCur->enDataType))
467 {
468 continue;
469 }
470
471 for (i = 0, pstCurParse = NULL; i < uiParseNum; i++)
472 {
473 if (0 == grub_strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName))
474 {
475 pstCurParse = pstJsonParse + i;
476 break;
477 }
478 }
479
480 if (NULL == pstCurParse)
481 {
482 continue;
483 }
484
485 switch (pstJsonCur->enDataType)
486 {
487 case JSON_TYPE_NUMBER:
488 {
489 if (sizeof(grub_uint32_t) == pstCurParse->uiBufSize)
490 {
491 *(grub_uint32_t *)(pstCurParse->pDataBuf) = (grub_uint32_t)pstJsonCur->unData.lValue;
492 }
493 else if (sizeof(grub_uint16_t) == pstCurParse->uiBufSize)
494 {
495 *(grub_uint16_t *)(pstCurParse->pDataBuf) = (grub_uint16_t)pstJsonCur->unData.lValue;
496 }
497 else if (sizeof(grub_uint8_t) == pstCurParse->uiBufSize)
498 {
499 *(grub_uint8_t *)(pstCurParse->pDataBuf) = (grub_uint8_t)pstJsonCur->unData.lValue;
500 }
501 else if ((pstCurParse->uiBufSize > sizeof(grub_uint64_t)))
502 {
503 grub_snprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu",
504 (unsigned long long)(pstJsonCur->unData.lValue));
505 }
506 else
507 {
508 json_debug("Invalid number data buf size %u.", pstCurParse->uiBufSize);
509 }
510 break;
511 }
512 case JSON_TYPE_STRING:
513 {
514 grub_strncpy((char *)pstCurParse->pDataBuf, pstJsonCur->unData.pcStrVal, pstCurParse->uiBufSize);
515 break;
516 }
517 case JSON_TYPE_BOOL:
518 {
519 *(grub_uint8_t *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0;
520 break;
521 }
522 default :
523 {
524 break;
525 }
526 }
527 }
528
529 return JSON_SUCCESS;
530 }
531
532 int vtoy_json_scan_array
533 (
534 VTOY_JSON *pstJson,
535 const char *szKey,
536 VTOY_JSON **ppstArrayItem
537 )
538 {
539 VTOY_JSON *pstJsonItem = NULL;
540
541 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
542 if (NULL == pstJsonItem)
543 {
544 json_debug("Key %s is not found in json data.", szKey);
545 return JSON_NOT_FOUND;
546 }
547
548 *ppstArrayItem = pstJsonItem;
549
550 return JSON_SUCCESS;
551 }
552
553 int vtoy_json_scan_array_ex
554 (
555 VTOY_JSON *pstJson,
556 const char *szKey,
557 VTOY_JSON **ppstArrayItem
558 )
559 {
560 VTOY_JSON *pstJsonItem = NULL;
561
562 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
563 if (NULL == pstJsonItem)
564 {
565 json_debug("Key %s is not found in json data.", szKey);
566 return JSON_NOT_FOUND;
567 }
568
569 *ppstArrayItem = pstJsonItem->pstChild;
570
571 return JSON_SUCCESS;
572 }
573
574 int vtoy_json_scan_object
575 (
576 VTOY_JSON *pstJson,
577 const char *szKey,
578 VTOY_JSON **ppstObjectItem
579 )
580 {
581 VTOY_JSON *pstJsonItem = NULL;
582
583 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey);
584 if (NULL == pstJsonItem)
585 {
586 json_debug("Key %s is not found in json data.", szKey);
587 return JSON_NOT_FOUND;
588 }
589
590 *ppstObjectItem = pstJsonItem;
591
592 return JSON_SUCCESS;
593 }
594
595 int vtoy_json_get_int
596 (
597 VTOY_JSON *pstJson,
598 const char *szKey,
599 int *piValue
600 )
601 {
602 VTOY_JSON *pstJsonItem = NULL;
603
604 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
605 if (NULL == pstJsonItem)
606 {
607 json_debug("Key %s is not found in json data.", szKey);
608 return JSON_NOT_FOUND;
609 }
610
611 *piValue = (int)pstJsonItem->unData.lValue;
612
613 return JSON_SUCCESS;
614 }
615
616 int vtoy_json_get_uint
617 (
618 VTOY_JSON *pstJson,
619 const char *szKey,
620 grub_uint32_t *puiValue
621 )
622 {
623 VTOY_JSON *pstJsonItem = NULL;
624
625 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
626 if (NULL == pstJsonItem)
627 {
628 json_debug("Key %s is not found in json data.", szKey);
629 return JSON_NOT_FOUND;
630 }
631
632 *puiValue = (grub_uint32_t)pstJsonItem->unData.lValue;
633
634 return JSON_SUCCESS;
635 }
636
637 int vtoy_json_get_uint64
638 (
639 VTOY_JSON *pstJson,
640 const char *szKey,
641 grub_uint64_t *pui64Value
642 )
643 {
644 VTOY_JSON *pstJsonItem = NULL;
645
646 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
647 if (NULL == pstJsonItem)
648 {
649 json_debug("Key %s is not found in json data.", szKey);
650 return JSON_NOT_FOUND;
651 }
652
653 *pui64Value = (grub_uint64_t)pstJsonItem->unData.lValue;
654
655 return JSON_SUCCESS;
656 }
657
658 int vtoy_json_get_bool
659 (
660 VTOY_JSON *pstJson,
661 const char *szKey,
662 grub_uint8_t *pbValue
663 )
664 {
665 VTOY_JSON *pstJsonItem = NULL;
666
667 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_BOOL, szKey);
668 if (NULL == pstJsonItem)
669 {
670 json_debug("Key %s is not found in json data.", szKey);
671 return JSON_NOT_FOUND;
672 }
673
674 *pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0;
675
676 return JSON_SUCCESS;
677 }
678
679 int vtoy_json_get_string
680 (
681 VTOY_JSON *pstJson,
682 const char *szKey,
683 grub_uint32_t uiBufLen,
684 char *pcBuf
685 )
686 {
687 VTOY_JSON *pstJsonItem = NULL;
688
689 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
690 if (NULL == pstJsonItem)
691 {
692 json_debug("Key %s is not found in json data.", szKey);
693 return JSON_NOT_FOUND;
694 }
695
696 grub_strncpy(pcBuf, pstJsonItem->unData.pcStrVal, uiBufLen);
697
698 return JSON_SUCCESS;
699 }
700
701 const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey)
702 {
703 VTOY_JSON *pstJsonItem = NULL;
704
705 if ((NULL == pstJson) || (NULL == szKey))
706 {
707 return NULL;
708 }
709
710 pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
711 if (NULL == pstJsonItem)
712 {
713 json_debug("Key %s is not found in json data.", szKey);
714 return NULL;
715 }
716
717 return pstJsonItem->unData.pcStrVal;
718 }
719
720 int vtoy_json_destroy(VTOY_JSON *pstJson)
721 {
722 if (NULL == pstJson)
723 {
724 return JSON_SUCCESS;
725 }
726
727 if (NULL != pstJson->pstChild)
728 {
729 vtoy_json_free(pstJson->pstChild);
730 }
731
732 if (NULL != pstJson->pstNext)
733 {
734 vtoy_json_free(pstJson->pstNext);
735 }
736
737 grub_free(pstJson);
738
739 return JSON_SUCCESS;
740 }
741