diff options
Diffstat (limited to 'src/json/json_helper.c')
-rw-r--r-- | src/json/json_helper.c | 993 |
1 files changed, 0 insertions, 993 deletions
diff --git a/src/json/json_helper.c b/src/json/json_helper.c deleted file mode 100644 index 55435ea19..000000000 --- a/src/json/json_helper.c +++ /dev/null | |||
@@ -1,993 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2014, 2015, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file json/json_helper.c | ||
22 | * @brief functions to generate specifciations for JSON parsing | ||
23 | * @author Florian Dold | ||
24 | * @author Benedikt Mueller | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_json_lib.h" | ||
29 | |||
30 | |||
31 | struct GNUNET_JSON_Specification | ||
32 | GNUNET_JSON_spec_end () | ||
33 | { | ||
34 | struct GNUNET_JSON_Specification ret = { | ||
35 | .parser = NULL, | ||
36 | .cleaner = NULL, | ||
37 | .cls = NULL | ||
38 | }; | ||
39 | |||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | |||
44 | /** | ||
45 | * Parse given JSON object to fixed size data | ||
46 | * | ||
47 | * @param cls closure, NULL | ||
48 | * @param root the json object representing data | ||
49 | * @param[out] spec where to write the data | ||
50 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
51 | */ | ||
52 | static int | ||
53 | parse_fixed_data (void *cls, | ||
54 | json_t *root, | ||
55 | struct GNUNET_JSON_Specification *spec) | ||
56 | { | ||
57 | const char *enc; | ||
58 | unsigned int len; | ||
59 | |||
60 | if (NULL == (enc = json_string_value (root))) | ||
61 | { | ||
62 | GNUNET_break_op (0); | ||
63 | return GNUNET_SYSERR; | ||
64 | } | ||
65 | len = strlen (enc); | ||
66 | if (((len * 5) / 8) != spec->ptr_size) | ||
67 | { | ||
68 | GNUNET_break_op (0); | ||
69 | return GNUNET_SYSERR; | ||
70 | } | ||
71 | if (GNUNET_OK != | ||
72 | GNUNET_STRINGS_string_to_data (enc, | ||
73 | len, | ||
74 | spec->ptr, | ||
75 | spec->ptr_size)) | ||
76 | { | ||
77 | GNUNET_break_op (0); | ||
78 | return GNUNET_SYSERR; | ||
79 | } | ||
80 | return GNUNET_OK; | ||
81 | } | ||
82 | |||
83 | |||
84 | struct GNUNET_JSON_Specification | ||
85 | GNUNET_JSON_spec_fixed (const char *name, | ||
86 | void *obj, | ||
87 | size_t size) | ||
88 | { | ||
89 | struct GNUNET_JSON_Specification ret = { | ||
90 | .parser = &parse_fixed_data, | ||
91 | .cleaner = NULL, | ||
92 | .cls = NULL, | ||
93 | .field = name, | ||
94 | .ptr = obj, | ||
95 | .ptr_size = size, | ||
96 | .size_ptr = NULL | ||
97 | }; | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Parse given JSON object to variable size data | ||
105 | * | ||
106 | * @param cls closure, NULL | ||
107 | * @param root the json object representing data | ||
108 | * @param[out] spec where to write the data | ||
109 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
110 | */ | ||
111 | static int | ||
112 | parse_variable_data (void *cls, | ||
113 | json_t *root, | ||
114 | struct GNUNET_JSON_Specification *spec) | ||
115 | { | ||
116 | const char *str; | ||
117 | size_t size; | ||
118 | void *data; | ||
119 | |||
120 | str = json_string_value (root); | ||
121 | if (NULL == str) | ||
122 | { | ||
123 | GNUNET_break_op (0); | ||
124 | return GNUNET_SYSERR; | ||
125 | } | ||
126 | if (GNUNET_OK != | ||
127 | GNUNET_STRINGS_string_to_data_alloc (str, | ||
128 | strlen (str), | ||
129 | &data, | ||
130 | &size)) | ||
131 | { | ||
132 | GNUNET_break_op (0); | ||
133 | return GNUNET_SYSERR; | ||
134 | } | ||
135 | *(void **) spec->ptr = data; | ||
136 | *spec->size_ptr = size; | ||
137 | return GNUNET_OK; | ||
138 | } | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Cleanup data left from parsing variable size data | ||
143 | * | ||
144 | * @param cls closure, NULL | ||
145 | * @param[out] spec where to free the data | ||
146 | */ | ||
147 | static void | ||
148 | clean_variable_data (void *cls, | ||
149 | struct GNUNET_JSON_Specification *spec) | ||
150 | { | ||
151 | (void) cls; | ||
152 | if (0 != *spec->size_ptr) | ||
153 | { | ||
154 | GNUNET_free (*(void **) spec->ptr); | ||
155 | *(void **) spec->ptr = NULL; | ||
156 | *spec->size_ptr = 0; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | struct GNUNET_JSON_Specification | ||
162 | GNUNET_JSON_spec_varsize (const char *name, | ||
163 | void **obj, | ||
164 | size_t *size) | ||
165 | { | ||
166 | struct GNUNET_JSON_Specification ret = { | ||
167 | .parser = &parse_variable_data, | ||
168 | .cleaner = &clean_variable_data, | ||
169 | .cls = NULL, | ||
170 | .field = name, | ||
171 | .ptr = obj, | ||
172 | .ptr_size = 0, | ||
173 | .size_ptr = size | ||
174 | }; | ||
175 | |||
176 | *obj = NULL; | ||
177 | *size = 0; | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Parse given JSON object to string. | ||
184 | * | ||
185 | * @param cls closure, NULL | ||
186 | * @param root the json object representing data | ||
187 | * @param[out] spec where to write the data | ||
188 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
189 | */ | ||
190 | static int | ||
191 | parse_string (void *cls, | ||
192 | json_t *root, | ||
193 | struct GNUNET_JSON_Specification *spec) | ||
194 | { | ||
195 | const char *str; | ||
196 | |||
197 | (void) cls; | ||
198 | str = json_string_value (root); | ||
199 | if (NULL == str) | ||
200 | { | ||
201 | GNUNET_break_op (0); | ||
202 | return GNUNET_SYSERR; | ||
203 | } | ||
204 | *(const char **) spec->ptr = str; | ||
205 | return GNUNET_OK; | ||
206 | } | ||
207 | |||
208 | |||
209 | struct GNUNET_JSON_Specification | ||
210 | GNUNET_JSON_spec_string (const char *name, | ||
211 | const char **strptr) | ||
212 | { | ||
213 | struct GNUNET_JSON_Specification ret = { | ||
214 | .parser = &parse_string, | ||
215 | .cleaner = NULL, | ||
216 | .cls = NULL, | ||
217 | .field = name, | ||
218 | .ptr = strptr, | ||
219 | .ptr_size = 0, | ||
220 | .size_ptr = NULL | ||
221 | }; | ||
222 | |||
223 | *strptr = NULL; | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | |||
228 | /** | ||
229 | * Parse given JSON object to a JSON object. (Yes, trivial.) | ||
230 | * | ||
231 | * @param cls closure, NULL | ||
232 | * @param root the json object representing data | ||
233 | * @param[out] spec where to write the data | ||
234 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
235 | */ | ||
236 | static int | ||
237 | parse_object (void *cls, | ||
238 | json_t *root, | ||
239 | struct GNUNET_JSON_Specification *spec) | ||
240 | { | ||
241 | if (! (json_is_object (root) || json_is_array (root))) | ||
242 | { | ||
243 | GNUNET_break_op (0); | ||
244 | return GNUNET_SYSERR; | ||
245 | } | ||
246 | json_incref (root); | ||
247 | *(json_t **) spec->ptr = root; | ||
248 | return GNUNET_OK; | ||
249 | } | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Cleanup data left from parsing JSON object. | ||
254 | * | ||
255 | * @param cls closure, NULL | ||
256 | * @param[out] spec where to free the data | ||
257 | */ | ||
258 | static void | ||
259 | clean_object (void *cls, | ||
260 | struct GNUNET_JSON_Specification *spec) | ||
261 | { | ||
262 | json_t **ptr = (json_t **) spec->ptr; | ||
263 | |||
264 | if (NULL != *ptr) | ||
265 | { | ||
266 | json_decref (*ptr); | ||
267 | *ptr = NULL; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | |||
272 | struct GNUNET_JSON_Specification | ||
273 | GNUNET_JSON_spec_json (const char *name, | ||
274 | json_t **jsonp) | ||
275 | { | ||
276 | struct GNUNET_JSON_Specification ret = { | ||
277 | .parser = &parse_object, | ||
278 | .cleaner = &clean_object, | ||
279 | .cls = NULL, | ||
280 | .field = name, | ||
281 | .ptr = jsonp, | ||
282 | .ptr_size = 0, | ||
283 | .size_ptr = NULL | ||
284 | }; | ||
285 | |||
286 | *jsonp = NULL; | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | |||
291 | /** | ||
292 | * Parse given JSON object to a bool. | ||
293 | * | ||
294 | * @param cls closure, NULL | ||
295 | * @param root the json object representing data | ||
296 | * @param[out] spec where to write the data | ||
297 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
298 | */ | ||
299 | static int | ||
300 | parse_bool (void *cls, | ||
301 | json_t *root, | ||
302 | struct GNUNET_JSON_Specification *spec) | ||
303 | { | ||
304 | bool *b = spec->ptr; | ||
305 | |||
306 | if (json_true () == root) | ||
307 | { | ||
308 | *b = true; | ||
309 | return GNUNET_OK; | ||
310 | } | ||
311 | if (json_false () == root) | ||
312 | { | ||
313 | *b = false; | ||
314 | return GNUNET_OK; | ||
315 | } | ||
316 | GNUNET_break_op (0); | ||
317 | return GNUNET_SYSERR; | ||
318 | } | ||
319 | |||
320 | |||
321 | struct GNUNET_JSON_Specification | ||
322 | GNUNET_JSON_spec_bool (const char *name, | ||
323 | bool *b) | ||
324 | { | ||
325 | struct GNUNET_JSON_Specification ret = { | ||
326 | .parser = &parse_bool, | ||
327 | .cleaner = NULL, | ||
328 | .cls = NULL, | ||
329 | .field = name, | ||
330 | .ptr = b, | ||
331 | .ptr_size = sizeof(bool), | ||
332 | .size_ptr = NULL | ||
333 | }; | ||
334 | |||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | |||
339 | /** | ||
340 | * Parse given JSON object to a uint8_t. | ||
341 | * | ||
342 | * @param cls closure, NULL | ||
343 | * @param root the json object representing data | ||
344 | * @param[out] spec where to write the data | ||
345 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
346 | */ | ||
347 | static int | ||
348 | parse_u8 (void *cls, | ||
349 | json_t *root, | ||
350 | struct GNUNET_JSON_Specification *spec) | ||
351 | { | ||
352 | json_int_t val; | ||
353 | uint8_t *up = spec->ptr; | ||
354 | |||
355 | if (! json_is_integer (root)) | ||
356 | { | ||
357 | GNUNET_break_op (0); | ||
358 | return GNUNET_SYSERR; | ||
359 | } | ||
360 | val = json_integer_value (root); | ||
361 | if ((0 > val) || (val > UINT8_MAX)) | ||
362 | { | ||
363 | GNUNET_break_op (0); | ||
364 | return GNUNET_SYSERR; | ||
365 | } | ||
366 | *up = (uint8_t) val; | ||
367 | return GNUNET_OK; | ||
368 | } | ||
369 | |||
370 | |||
371 | struct GNUNET_JSON_Specification | ||
372 | GNUNET_JSON_spec_uint8 (const char *name, | ||
373 | uint8_t *u8) | ||
374 | { | ||
375 | struct GNUNET_JSON_Specification ret = { | ||
376 | .parser = &parse_u8, | ||
377 | .cleaner = NULL, | ||
378 | .cls = NULL, | ||
379 | .field = name, | ||
380 | .ptr = u8, | ||
381 | .ptr_size = sizeof(uint8_t), | ||
382 | .size_ptr = NULL | ||
383 | }; | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | |||
389 | /** | ||
390 | * Parse given JSON object to a uint16_t. | ||
391 | * | ||
392 | * @param cls closure, NULL | ||
393 | * @param root the json object representing data | ||
394 | * @param[out] spec where to write the data | ||
395 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
396 | */ | ||
397 | static int | ||
398 | parse_u16 (void *cls, | ||
399 | json_t *root, | ||
400 | struct GNUNET_JSON_Specification *spec) | ||
401 | { | ||
402 | json_int_t val; | ||
403 | uint16_t *up = spec->ptr; | ||
404 | |||
405 | if (! json_is_integer (root)) | ||
406 | { | ||
407 | GNUNET_break_op (0); | ||
408 | return GNUNET_SYSERR; | ||
409 | } | ||
410 | val = json_integer_value (root); | ||
411 | if ((0 > val) || (val > UINT16_MAX)) | ||
412 | { | ||
413 | GNUNET_break_op (0); | ||
414 | return GNUNET_SYSERR; | ||
415 | } | ||
416 | *up = (uint16_t) val; | ||
417 | return GNUNET_OK; | ||
418 | } | ||
419 | |||
420 | |||
421 | struct GNUNET_JSON_Specification | ||
422 | GNUNET_JSON_spec_uint16 (const char *name, | ||
423 | uint16_t *u16) | ||
424 | { | ||
425 | struct GNUNET_JSON_Specification ret = { | ||
426 | .parser = &parse_u16, | ||
427 | .cleaner = NULL, | ||
428 | .cls = NULL, | ||
429 | .field = name, | ||
430 | .ptr = u16, | ||
431 | .ptr_size = sizeof(uint16_t), | ||
432 | .size_ptr = NULL | ||
433 | }; | ||
434 | |||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | |||
439 | /** | ||
440 | * Parse given JSON object to a uint32_t. | ||
441 | * | ||
442 | * @param cls closure, NULL | ||
443 | * @param root the json object representing data | ||
444 | * @param[out] spec where to write the data | ||
445 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
446 | */ | ||
447 | static int | ||
448 | parse_u32 (void *cls, | ||
449 | json_t *root, | ||
450 | struct GNUNET_JSON_Specification *spec) | ||
451 | { | ||
452 | json_int_t val; | ||
453 | uint32_t *up = spec->ptr; | ||
454 | |||
455 | if (! json_is_integer (root)) | ||
456 | { | ||
457 | GNUNET_break_op (0); | ||
458 | return GNUNET_SYSERR; | ||
459 | } | ||
460 | val = json_integer_value (root); | ||
461 | if ((0 > val) || (val > UINT32_MAX)) | ||
462 | { | ||
463 | GNUNET_break_op (0); | ||
464 | return GNUNET_SYSERR; | ||
465 | } | ||
466 | *up = (uint32_t) val; | ||
467 | return GNUNET_OK; | ||
468 | } | ||
469 | |||
470 | |||
471 | struct GNUNET_JSON_Specification | ||
472 | GNUNET_JSON_spec_uint32 (const char *name, | ||
473 | uint32_t *u32) | ||
474 | { | ||
475 | struct GNUNET_JSON_Specification ret = { | ||
476 | .parser = &parse_u32, | ||
477 | .cleaner = NULL, | ||
478 | .cls = NULL, | ||
479 | .field = name, | ||
480 | .ptr = u32, | ||
481 | .ptr_size = sizeof(uint32_t), | ||
482 | .size_ptr = NULL | ||
483 | }; | ||
484 | |||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | |||
489 | /** | ||
490 | * Parse given JSON object to a uint64_t. | ||
491 | * | ||
492 | * @param cls closure, NULL | ||
493 | * @param root the json object representing data | ||
494 | * @param[out] spec where to write the data | ||
495 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
496 | */ | ||
497 | static int | ||
498 | parse_u64 (void *cls, | ||
499 | json_t *root, | ||
500 | struct GNUNET_JSON_Specification *spec) | ||
501 | { | ||
502 | json_int_t val; | ||
503 | uint64_t *up = spec->ptr; | ||
504 | |||
505 | if (! json_is_integer (root)) | ||
506 | { | ||
507 | GNUNET_break_op (0); | ||
508 | return GNUNET_SYSERR; | ||
509 | } | ||
510 | val = json_integer_value (root); | ||
511 | *up = (uint64_t) val; | ||
512 | return GNUNET_OK; | ||
513 | } | ||
514 | |||
515 | |||
516 | struct GNUNET_JSON_Specification | ||
517 | GNUNET_JSON_spec_uint64 (const char *name, | ||
518 | uint64_t *u64) | ||
519 | { | ||
520 | struct GNUNET_JSON_Specification ret = { | ||
521 | .parser = &parse_u64, | ||
522 | .cleaner = NULL, | ||
523 | .cls = NULL, | ||
524 | .field = name, | ||
525 | .ptr = u64, | ||
526 | .ptr_size = sizeof(uint64_t), | ||
527 | .size_ptr = NULL | ||
528 | }; | ||
529 | |||
530 | return ret; | ||
531 | } | ||
532 | |||
533 | |||
534 | /** | ||
535 | * Parse given JSON object to a int64_t. | ||
536 | * | ||
537 | * @param cls closure, NULL | ||
538 | * @param root the json object representing data | ||
539 | * @param[out] spec where to write the data | ||
540 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
541 | */ | ||
542 | static int | ||
543 | parse_i64 (void *cls, | ||
544 | json_t *root, | ||
545 | struct GNUNET_JSON_Specification *spec) | ||
546 | { | ||
547 | json_int_t val; | ||
548 | int64_t *up = spec->ptr; | ||
549 | |||
550 | if (! json_is_integer (root)) | ||
551 | { | ||
552 | GNUNET_break_op (0); | ||
553 | return GNUNET_SYSERR; | ||
554 | } | ||
555 | val = json_integer_value (root); | ||
556 | *up = (int64_t) val; | ||
557 | return GNUNET_OK; | ||
558 | } | ||
559 | |||
560 | |||
561 | struct GNUNET_JSON_Specification | ||
562 | GNUNET_JSON_spec_int64 (const char *name, | ||
563 | int64_t *i64) | ||
564 | { | ||
565 | struct GNUNET_JSON_Specification ret = { | ||
566 | .parser = &parse_i64, | ||
567 | .cleaner = NULL, | ||
568 | .cls = NULL, | ||
569 | .field = name, | ||
570 | .ptr = i64, | ||
571 | .ptr_size = sizeof(int64_t), | ||
572 | .size_ptr = NULL | ||
573 | }; | ||
574 | |||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | |||
579 | /* ************ GNUnet-specific parser specifications ******************* */ | ||
580 | |||
581 | /** | ||
582 | * Parse given JSON object to absolute time. | ||
583 | * | ||
584 | * @param cls closure, NULL | ||
585 | * @param root the json object representing data | ||
586 | * @param[out] spec where to write the data | ||
587 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
588 | */ | ||
589 | static int | ||
590 | parse_abs_time (void *cls, | ||
591 | json_t *root, | ||
592 | struct GNUNET_JSON_Specification *spec) | ||
593 | { | ||
594 | struct GNUNET_TIME_Absolute *abs = spec->ptr; | ||
595 | json_t *json_t_ms; | ||
596 | unsigned long long int tval; | ||
597 | |||
598 | if (! json_is_object (root)) | ||
599 | { | ||
600 | GNUNET_break_op (0); | ||
601 | return GNUNET_SYSERR; | ||
602 | } | ||
603 | json_t_ms = json_object_get (root, "t_ms"); | ||
604 | if (json_is_integer (json_t_ms)) | ||
605 | { | ||
606 | tval = json_integer_value (json_t_ms); | ||
607 | /* Time is in milliseconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ | ||
608 | abs->abs_value_us = tval * GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; | ||
609 | if ((abs->abs_value_us) | ||
610 | / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us | ||
611 | != tval) | ||
612 | { | ||
613 | /* Integer overflow */ | ||
614 | GNUNET_break_op (0); | ||
615 | return GNUNET_SYSERR; | ||
616 | } | ||
617 | return GNUNET_OK; | ||
618 | } | ||
619 | if (json_is_string (json_t_ms)) | ||
620 | { | ||
621 | const char *val; | ||
622 | |||
623 | val = json_string_value (json_t_ms); | ||
624 | if ((0 == strcasecmp (val, "never"))) | ||
625 | { | ||
626 | *abs = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
627 | return GNUNET_OK; | ||
628 | } | ||
629 | GNUNET_break_op (0); | ||
630 | return GNUNET_SYSERR; | ||
631 | } | ||
632 | GNUNET_break_op (0); | ||
633 | return GNUNET_SYSERR; | ||
634 | } | ||
635 | |||
636 | |||
637 | struct GNUNET_JSON_Specification | ||
638 | GNUNET_JSON_spec_absolute_time (const char *name, | ||
639 | struct GNUNET_TIME_Absolute *at) | ||
640 | { | ||
641 | struct GNUNET_JSON_Specification ret = { | ||
642 | .parser = &parse_abs_time, | ||
643 | .cleaner = NULL, | ||
644 | .cls = NULL, | ||
645 | .field = name, | ||
646 | .ptr = at, | ||
647 | .ptr_size = sizeof(struct GNUNET_TIME_Absolute), | ||
648 | .size_ptr = NULL | ||
649 | }; | ||
650 | |||
651 | return ret; | ||
652 | } | ||
653 | |||
654 | |||
655 | /** | ||
656 | * Parse given JSON object to absolute time. | ||
657 | * | ||
658 | * @param cls closure, NULL | ||
659 | * @param root the json object representing data | ||
660 | * @param[out] spec where to write the data | ||
661 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
662 | */ | ||
663 | static int | ||
664 | parse_abs_time_nbo (void *cls, | ||
665 | json_t *root, | ||
666 | struct GNUNET_JSON_Specification *spec) | ||
667 | { | ||
668 | struct GNUNET_TIME_AbsoluteNBO *abs = spec->ptr; | ||
669 | struct GNUNET_TIME_Absolute a; | ||
670 | struct GNUNET_JSON_Specification ispec; | ||
671 | |||
672 | ispec = *spec; | ||
673 | ispec.parser = &parse_abs_time; | ||
674 | ispec.ptr = &a; | ||
675 | if (GNUNET_OK != | ||
676 | parse_abs_time (NULL, | ||
677 | root, | ||
678 | &ispec)) | ||
679 | return GNUNET_SYSERR; | ||
680 | *abs = GNUNET_TIME_absolute_hton (a); | ||
681 | return GNUNET_OK; | ||
682 | } | ||
683 | |||
684 | |||
685 | struct GNUNET_JSON_Specification | ||
686 | GNUNET_JSON_spec_absolute_time_nbo (const char *name, | ||
687 | struct GNUNET_TIME_AbsoluteNBO *at) | ||
688 | { | ||
689 | struct GNUNET_JSON_Specification ret = { | ||
690 | .parser = &parse_abs_time_nbo, | ||
691 | .cleaner = NULL, | ||
692 | .cls = NULL, | ||
693 | .field = name, | ||
694 | .ptr = at, | ||
695 | .ptr_size = sizeof(struct GNUNET_TIME_AbsoluteNBO), | ||
696 | .size_ptr = NULL | ||
697 | }; | ||
698 | |||
699 | return ret; | ||
700 | } | ||
701 | |||
702 | |||
703 | /** | ||
704 | * Parse given JSON object to relative time. | ||
705 | * | ||
706 | * @param cls closure, NULL | ||
707 | * @param root the json object representing data | ||
708 | * @param[out] spec where to write the data | ||
709 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
710 | */ | ||
711 | static int | ||
712 | parse_rel_time (void *cls, | ||
713 | json_t *root, | ||
714 | struct GNUNET_JSON_Specification *spec) | ||
715 | { | ||
716 | struct GNUNET_TIME_Relative *rel = spec->ptr; | ||
717 | json_t *json_d_ms; | ||
718 | unsigned long long int tval; | ||
719 | |||
720 | if (! json_is_object (root)) | ||
721 | { | ||
722 | GNUNET_break_op (0); | ||
723 | return GNUNET_SYSERR; | ||
724 | } | ||
725 | json_d_ms = json_object_get (root, "d_ms"); | ||
726 | if (json_is_integer (json_d_ms)) | ||
727 | { | ||
728 | tval = json_integer_value (json_d_ms); | ||
729 | /* Time is in milliseconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ | ||
730 | rel->rel_value_us = tval * 1000LL; | ||
731 | if ((rel->rel_value_us) / 1000LL != tval) | ||
732 | { | ||
733 | /* Integer overflow */ | ||
734 | GNUNET_break_op (0); | ||
735 | return GNUNET_SYSERR; | ||
736 | } | ||
737 | return GNUNET_OK; | ||
738 | } | ||
739 | if (json_is_string (json_d_ms)) | ||
740 | { | ||
741 | const char *val; | ||
742 | val = json_string_value (json_d_ms); | ||
743 | if ((0 == strcasecmp (val, "forever"))) | ||
744 | { | ||
745 | *rel = GNUNET_TIME_UNIT_FOREVER_REL; | ||
746 | return GNUNET_OK; | ||
747 | } | ||
748 | GNUNET_break_op (0); | ||
749 | return GNUNET_SYSERR; | ||
750 | } | ||
751 | GNUNET_break_op (0); | ||
752 | return GNUNET_SYSERR; | ||
753 | } | ||
754 | |||
755 | |||
756 | struct GNUNET_JSON_Specification | ||
757 | GNUNET_JSON_spec_relative_time (const char *name, | ||
758 | struct GNUNET_TIME_Relative *rt) | ||
759 | { | ||
760 | struct GNUNET_JSON_Specification ret = { | ||
761 | .parser = &parse_rel_time, | ||
762 | .cleaner = NULL, | ||
763 | .cls = NULL, | ||
764 | .field = name, | ||
765 | .ptr = rt, | ||
766 | .ptr_size = sizeof(struct GNUNET_TIME_Relative), | ||
767 | .size_ptr = NULL | ||
768 | }; | ||
769 | |||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | |||
774 | /** | ||
775 | * Parse given JSON object to RSA public key. | ||
776 | * | ||
777 | * @param cls closure, NULL | ||
778 | * @param root the json object representing data | ||
779 | * @param[out] spec where to write the data | ||
780 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
781 | */ | ||
782 | static int | ||
783 | parse_rsa_public_key (void *cls, | ||
784 | json_t *root, | ||
785 | struct GNUNET_JSON_Specification *spec) | ||
786 | { | ||
787 | struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr; | ||
788 | const char *enc; | ||
789 | char *buf; | ||
790 | size_t len; | ||
791 | size_t buf_len; | ||
792 | |||
793 | if (NULL == (enc = json_string_value (root))) | ||
794 | { | ||
795 | GNUNET_break_op (0); | ||
796 | return GNUNET_SYSERR; | ||
797 | } | ||
798 | len = strlen (enc); | ||
799 | buf_len = (len * 5) / 8; | ||
800 | buf = GNUNET_malloc (buf_len); | ||
801 | if (GNUNET_OK != | ||
802 | GNUNET_STRINGS_string_to_data (enc, | ||
803 | len, | ||
804 | buf, | ||
805 | buf_len)) | ||
806 | { | ||
807 | GNUNET_break_op (0); | ||
808 | GNUNET_free (buf); | ||
809 | return GNUNET_SYSERR; | ||
810 | } | ||
811 | if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf, | ||
812 | buf_len))) | ||
813 | { | ||
814 | GNUNET_break_op (0); | ||
815 | GNUNET_free (buf); | ||
816 | return GNUNET_SYSERR; | ||
817 | } | ||
818 | GNUNET_free (buf); | ||
819 | return GNUNET_OK; | ||
820 | } | ||
821 | |||
822 | |||
823 | /** | ||
824 | * Cleanup data left from parsing RSA public key. | ||
825 | * | ||
826 | * @param cls closure, NULL | ||
827 | * @param[out] spec where to free the data | ||
828 | */ | ||
829 | static void | ||
830 | clean_rsa_public_key (void *cls, | ||
831 | struct GNUNET_JSON_Specification *spec) | ||
832 | { | ||
833 | struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr; | ||
834 | |||
835 | if (NULL != *pk) | ||
836 | { | ||
837 | GNUNET_CRYPTO_rsa_public_key_free (*pk); | ||
838 | *pk = NULL; | ||
839 | } | ||
840 | } | ||
841 | |||
842 | |||
843 | struct GNUNET_JSON_Specification | ||
844 | GNUNET_JSON_spec_rsa_public_key (const char *name, | ||
845 | struct GNUNET_CRYPTO_RsaPublicKey **pk) | ||
846 | { | ||
847 | struct GNUNET_JSON_Specification ret = { | ||
848 | .parser = &parse_rsa_public_key, | ||
849 | .cleaner = &clean_rsa_public_key, | ||
850 | .cls = NULL, | ||
851 | .field = name, | ||
852 | .ptr = pk, | ||
853 | .ptr_size = 0, | ||
854 | .size_ptr = NULL | ||
855 | }; | ||
856 | |||
857 | *pk = NULL; | ||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | |||
862 | /** | ||
863 | * Parse given JSON object to RSA signature. | ||
864 | * | ||
865 | * @param cls closure, NULL | ||
866 | * @param root the json object representing data | ||
867 | * @param[out] spec where to write the data | ||
868 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
869 | */ | ||
870 | static int | ||
871 | parse_rsa_signature (void *cls, | ||
872 | json_t *root, | ||
873 | struct GNUNET_JSON_Specification *spec) | ||
874 | { | ||
875 | struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr; | ||
876 | size_t size; | ||
877 | const char *str; | ||
878 | int res; | ||
879 | void *buf; | ||
880 | |||
881 | str = json_string_value (root); | ||
882 | if (NULL == str) | ||
883 | { | ||
884 | GNUNET_break_op (0); | ||
885 | return GNUNET_SYSERR; | ||
886 | } | ||
887 | size = (strlen (str) * 5) / 8; | ||
888 | buf = GNUNET_malloc (size); | ||
889 | res = GNUNET_STRINGS_string_to_data (str, | ||
890 | strlen (str), | ||
891 | buf, | ||
892 | size); | ||
893 | if (GNUNET_OK != res) | ||
894 | { | ||
895 | GNUNET_free (buf); | ||
896 | GNUNET_break_op (0); | ||
897 | return GNUNET_SYSERR; | ||
898 | } | ||
899 | if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf, | ||
900 | size))) | ||
901 | { | ||
902 | GNUNET_break_op (0); | ||
903 | GNUNET_free (buf); | ||
904 | return GNUNET_SYSERR; | ||
905 | } | ||
906 | GNUNET_free (buf); | ||
907 | return GNUNET_OK; | ||
908 | } | ||
909 | |||
910 | |||
911 | /** | ||
912 | * Cleanup data left from parsing RSA signature. | ||
913 | * | ||
914 | * @param cls closure, NULL | ||
915 | * @param[out] spec where to free the data | ||
916 | */ | ||
917 | static void | ||
918 | clean_rsa_signature (void *cls, | ||
919 | struct GNUNET_JSON_Specification *spec) | ||
920 | { | ||
921 | struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr; | ||
922 | |||
923 | if (NULL != *sig) | ||
924 | { | ||
925 | GNUNET_CRYPTO_rsa_signature_free (*sig); | ||
926 | *sig = NULL; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | |||
931 | struct GNUNET_JSON_Specification | ||
932 | GNUNET_JSON_spec_rsa_signature (const char *name, | ||
933 | struct GNUNET_CRYPTO_RsaSignature **sig) | ||
934 | { | ||
935 | struct GNUNET_JSON_Specification ret = { | ||
936 | .parser = &parse_rsa_signature, | ||
937 | .cleaner = &clean_rsa_signature, | ||
938 | .cls = NULL, | ||
939 | .field = name, | ||
940 | .ptr = sig, | ||
941 | .ptr_size = 0, | ||
942 | .size_ptr = NULL | ||
943 | }; | ||
944 | |||
945 | *sig = NULL; | ||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Parse given JSON object to an int as a boolean. | ||
952 | * | ||
953 | * @param cls closure, NULL | ||
954 | * @param root the json object representing data | ||
955 | * @param[out] spec where to write the data | ||
956 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
957 | */ | ||
958 | static int | ||
959 | parse_boolean (void *cls, | ||
960 | json_t *root, | ||
961 | struct GNUNET_JSON_Specification *spec) | ||
962 | { | ||
963 | int *bp = spec->ptr; | ||
964 | |||
965 | if (! json_is_boolean (root)) | ||
966 | { | ||
967 | GNUNET_break_op (0); | ||
968 | return GNUNET_SYSERR; | ||
969 | } | ||
970 | *bp = json_boolean_value (root) ? GNUNET_YES : GNUNET_NO; | ||
971 | return GNUNET_OK; | ||
972 | } | ||
973 | |||
974 | |||
975 | struct GNUNET_JSON_Specification | ||
976 | GNUNET_JSON_spec_boolean (const char *name, | ||
977 | int *boolean) | ||
978 | { | ||
979 | struct GNUNET_JSON_Specification ret = { | ||
980 | .parser = &parse_boolean, | ||
981 | .cleaner = NULL, | ||
982 | .cls = NULL, | ||
983 | .field = name, | ||
984 | .ptr = boolean, | ||
985 | .ptr_size = sizeof(int), | ||
986 | .size_ptr = NULL | ||
987 | }; | ||
988 | |||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | |||
993 | /* end of json_helper.c */ | ||