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