Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file json/json_helper.c
18 : * @brief helper functions to generate specifications to parse
19 : * Taler-specific JSON objects with libgnunetjson
20 : * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 : * @author Christian Grothoff
22 : */
23 : #include <gnunet/gnunet_util_lib.h>
24 : #include "taler/taler_util.h"
25 : #include "taler/taler_json_lib.h"
26 :
27 :
28 : /**
29 : * Convert string value to numeric cipher value.
30 : *
31 : * @param cipher_s input string
32 : * @return numeric cipher value
33 : */
34 : static enum GNUNET_CRYPTO_BlindSignatureAlgorithm
35 1015 : string_to_cipher (const char *cipher_s)
36 : {
37 1015 : if ((0 == strcasecmp (cipher_s,
38 542 : "RSA")) ||
39 542 : (0 == strcasecmp (cipher_s,
40 : "RSA+age_restricted")))
41 548 : return GNUNET_CRYPTO_BSA_RSA;
42 467 : if ((0 == strcasecmp (cipher_s,
43 70 : "CS")) ||
44 70 : (0 == strcasecmp (cipher_s,
45 : "CS+age_restricted")))
46 467 : return GNUNET_CRYPTO_BSA_CS;
47 0 : return GNUNET_CRYPTO_BSA_INVALID;
48 : }
49 :
50 :
51 : json_t *
52 5508 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
53 : {
54 5508 : char *amount_str = TALER_amount_to_string (amount);
55 :
56 5508 : GNUNET_assert (NULL != amount_str);
57 : {
58 5508 : json_t *j = json_string (amount_str);
59 :
60 5508 : GNUNET_free (amount_str);
61 5508 : return j;
62 : }
63 : }
64 :
65 :
66 : /**
67 : * Parse given JSON object to Amount
68 : *
69 : * @param cls closure, expected currency, or NULL
70 : * @param root the json object representing data
71 : * @param[out] spec where to write the data
72 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
73 : */
74 : static enum GNUNET_GenericReturnValue
75 7052 : parse_amount (void *cls,
76 : json_t *root,
77 : struct GNUNET_JSON_Specification *spec)
78 : {
79 7052 : const char *currency = cls;
80 7052 : struct TALER_Amount *r_amount = spec->ptr;
81 :
82 : (void) cls;
83 7052 : if (! json_is_string (root))
84 : {
85 0 : GNUNET_break_op (0);
86 0 : return GNUNET_SYSERR;
87 : }
88 7052 : if (GNUNET_OK !=
89 7052 : TALER_string_to_amount (json_string_value (root),
90 : r_amount))
91 : {
92 0 : GNUNET_break_op (0);
93 0 : return GNUNET_SYSERR;
94 : }
95 7052 : if ( (NULL != currency) &&
96 : (0 !=
97 4951 : strcasecmp (currency,
98 4951 : r_amount->currency)) )
99 : {
100 0 : GNUNET_break_op (0);
101 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
102 : "Expected currency `%s', but amount used currency `%s' in field `%s'\n",
103 : currency,
104 : r_amount->currency,
105 : spec->field);
106 0 : return GNUNET_SYSERR;
107 : }
108 7052 : return GNUNET_OK;
109 : }
110 :
111 :
112 : struct GNUNET_JSON_Specification
113 4980 : TALER_JSON_spec_amount (const char *name,
114 : const char *currency,
115 : struct TALER_Amount *r_amount)
116 : {
117 4980 : struct GNUNET_JSON_Specification ret = {
118 : .parser = &parse_amount,
119 : .cleaner = NULL,
120 : .cls = (void *) currency,
121 : .field = name,
122 : .ptr = r_amount,
123 : .ptr_size = 0,
124 : .size_ptr = NULL
125 : };
126 :
127 4980 : GNUNET_assert (NULL != currency);
128 4980 : return ret;
129 : }
130 :
131 :
132 : struct GNUNET_JSON_Specification
133 2209 : TALER_JSON_spec_amount_any (const char *name,
134 : struct TALER_Amount *r_amount)
135 : {
136 2209 : struct GNUNET_JSON_Specification ret = {
137 : .parser = &parse_amount,
138 : .cleaner = NULL,
139 : .cls = NULL,
140 : .field = name,
141 : .ptr = r_amount,
142 : .ptr_size = 0,
143 : .size_ptr = NULL
144 : };
145 :
146 2209 : return ret;
147 : }
148 :
149 :
150 : /**
151 : * Closure for parsing amount arrays.
152 : */
153 : struct AmountArrayCtx
154 : {
155 : /**
156 : * Pointer where to store the resulting array length.
157 : */
158 : size_t *len;
159 : };
160 :
161 :
162 : /**
163 : * Parse a JSON array of arbitrary amounts.
164 : */
165 : static enum GNUNET_GenericReturnValue
166 1 : parse_amount_any_array (void *cls,
167 : json_t *root,
168 : struct GNUNET_JSON_Specification *spec)
169 : {
170 1 : struct AmountArrayCtx *ctx = cls;
171 1 : struct TALER_Amount **out = spec->ptr;
172 :
173 1 : *out = NULL;
174 1 : if (NULL != ctx->len)
175 1 : *ctx->len = 0;
176 :
177 1 : if (! json_is_array (root))
178 : {
179 0 : GNUNET_break_op (0);
180 0 : return GNUNET_SYSERR;
181 : }
182 :
183 : {
184 1 : size_t len = json_array_size (root);
185 : json_t *entry;
186 : size_t idx;
187 :
188 1 : if (NULL != ctx->len)
189 1 : *ctx->len = len;
190 1 : if (0 == len)
191 : {
192 0 : *out = NULL;
193 0 : return GNUNET_OK;
194 : }
195 1 : *out = GNUNET_new_array (len,
196 : struct TALER_Amount);
197 3 : json_array_foreach (root, idx, entry) {
198 : const char *amount_str;
199 :
200 2 : if (! json_is_string (entry))
201 : {
202 0 : GNUNET_break_op (0);
203 0 : return GNUNET_SYSERR;
204 : }
205 2 : amount_str = json_string_value (entry);
206 2 : if (GNUNET_OK !=
207 2 : TALER_string_to_amount (amount_str,
208 2 : &(*out)[idx]))
209 : {
210 0 : GNUNET_break_op (0);
211 0 : return GNUNET_SYSERR;
212 : }
213 : }
214 : }
215 1 : return GNUNET_OK;
216 : }
217 :
218 :
219 : /**
220 : * Cleanup helper for the amount array parser.
221 : */
222 : static void
223 1 : clean_amount_any_array (void *cls,
224 : struct GNUNET_JSON_Specification *spec)
225 : {
226 1 : struct AmountArrayCtx *ctx = cls;
227 :
228 1 : if (NULL != spec->ptr)
229 : {
230 1 : GNUNET_free (*(void **) spec->ptr);
231 1 : *(void **) spec->ptr = NULL;
232 : }
233 1 : if ( (NULL != ctx) &&
234 1 : (NULL != ctx->len) )
235 1 : *ctx->len = 0;
236 1 : GNUNET_free (ctx);
237 1 : }
238 :
239 :
240 : struct GNUNET_JSON_Specification
241 1 : TALER_JSON_spec_amount_any_array (const char *field,
242 : size_t *amounts_len,
243 : struct TALER_Amount **amounts)
244 : {
245 : struct AmountArrayCtx *ctx;
246 :
247 1 : GNUNET_assert (NULL != amounts_len);
248 1 : GNUNET_assert (NULL != amounts);
249 1 : *amounts = NULL;
250 1 : *amounts_len = 0;
251 1 : ctx = GNUNET_new (struct AmountArrayCtx);
252 1 : ctx->len = amounts_len;
253 : {
254 1 : struct GNUNET_JSON_Specification ret = {
255 : .parser = &parse_amount_any_array,
256 : .cleaner = &clean_amount_any_array,
257 : .cls = ctx,
258 : .field = field,
259 : .ptr = amounts
260 : };
261 :
262 1 : return ret;
263 : }
264 : }
265 :
266 :
267 : /**
268 : * Parse a JSON array of amounts into a price list.
269 : *
270 : * @param cls closure, NULL
271 : * @param root the json array representing the price list
272 : * @param[out] spec where to write the data
273 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
274 : */
275 : static enum GNUNET_GenericReturnValue
276 4 : parse_amount_list (void *cls,
277 : json_t *root,
278 : struct GNUNET_JSON_Specification *spec)
279 : {
280 4 : struct TALER_AmountList *al = spec->ptr;
281 : size_t len;
282 : json_t *entry;
283 : size_t idx;
284 :
285 : (void) cls;
286 4 : al->tal = NULL;
287 4 : al->tal_len = 0;
288 4 : if (! json_is_array (root))
289 : {
290 0 : GNUNET_break_op (0);
291 0 : return GNUNET_SYSERR;
292 : }
293 4 : len = json_array_size (root);
294 4 : if (0 == len)
295 1 : return GNUNET_OK; /* empty price list: free */
296 3 : al->tal = GNUNET_new_array (len,
297 : struct TALER_Amount);
298 8 : json_array_foreach (root, idx, entry)
299 : {
300 7 : struct TALER_Amount *a = &al->tal[idx];
301 :
302 7 : if (! json_is_string (entry))
303 : {
304 0 : GNUNET_break_op (0);
305 0 : TALER_amount_list_free (al);
306 0 : return GNUNET_SYSERR;
307 : }
308 7 : if (GNUNET_OK !=
309 7 : TALER_string_to_amount (json_string_value (entry),
310 : a))
311 : {
312 1 : GNUNET_break_op (0);
313 1 : TALER_amount_list_free (al);
314 1 : return GNUNET_SYSERR;
315 : }
316 : /* only entries below @a idx are initialized so far, and
317 : #TALER_amount_list_find() must not look at the rest */
318 6 : al->tal_len = idx;
319 6 : if (NULL !=
320 6 : TALER_amount_list_find (al,
321 6 : a->currency))
322 : {
323 1 : GNUNET_break_op (0);
324 1 : TALER_amount_list_free (al);
325 1 : return GNUNET_SYSERR;
326 : }
327 5 : al->tal_len = idx + 1;
328 : }
329 1 : return GNUNET_OK;
330 : }
331 :
332 :
333 : /**
334 : * Cleanup helper for the price list parser.
335 : *
336 : * @param cls closure, NULL
337 : * @param[out] spec where to free the data
338 : */
339 : static void
340 4 : clean_amount_list (void *cls,
341 : struct GNUNET_JSON_Specification *spec)
342 : {
343 : (void) cls;
344 4 : TALER_amount_list_free (spec->ptr);
345 4 : }
346 :
347 :
348 : struct GNUNET_JSON_Specification
349 1 : TALER_JSON_spec_amount_list (const char *field,
350 : struct TALER_AmountList *al)
351 : {
352 1 : struct GNUNET_JSON_Specification ret = {
353 : .parser = &parse_amount_list,
354 : .cleaner = &clean_amount_list,
355 : .cls = NULL,
356 : .field = field,
357 : .ptr = al
358 : };
359 :
360 1 : GNUNET_assert (NULL != al);
361 1 : al->tal = NULL;
362 1 : al->tal_len = 0;
363 1 : return ret;
364 : }
365 :
366 :
367 : /**
368 : * Parse given JSON object to currency spec.
369 : *
370 : * @param cls closure, NULL
371 : * @param root the json object representing data
372 : * @param[out] spec where to write the data
373 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
374 : */
375 : static enum GNUNET_GenericReturnValue
376 42 : parse_cspec (void *cls,
377 : json_t *root,
378 : struct GNUNET_JSON_Specification *spec)
379 : {
380 42 : struct TALER_CurrencySpecification *r_cspec = spec->ptr;
381 42 : const char *currency = spec->cls;
382 : const char *name;
383 : uint32_t fid;
384 : uint32_t fnd;
385 : uint32_t ftzd;
386 : const json_t *map;
387 42 : const json_t *ca = NULL;
388 : struct GNUNET_JSON_Specification gspec[] = {
389 42 : GNUNET_JSON_spec_string ("name",
390 : &name),
391 42 : GNUNET_JSON_spec_uint32 ("num_fractional_input_digits",
392 : &fid),
393 42 : GNUNET_JSON_spec_uint32 ("num_fractional_normal_digits",
394 : &fnd),
395 42 : GNUNET_JSON_spec_uint32 ("num_fractional_trailing_zero_digits",
396 : &ftzd),
397 42 : GNUNET_JSON_spec_object_const ("alt_unit_names",
398 : &map),
399 42 : GNUNET_JSON_spec_mark_optional (
400 : GNUNET_JSON_spec_array_const ("common_amounts",
401 : &ca),
402 : NULL),
403 42 : GNUNET_JSON_spec_end ()
404 : };
405 : const char *emsg;
406 : unsigned int eline;
407 :
408 42 : memset (r_cspec->currency,
409 : 0,
410 : sizeof (r_cspec->currency));
411 42 : if (GNUNET_OK !=
412 42 : GNUNET_JSON_parse (root,
413 : gspec,
414 : &emsg,
415 : &eline))
416 : {
417 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418 : "Failed to parse %s at %u: %s\n",
419 : gspec[eline].field,
420 : eline,
421 : emsg);
422 0 : GNUNET_break_op (0);
423 0 : return GNUNET_SYSERR;
424 : }
425 42 : if (strlen (currency) >= TALER_CURRENCY_LEN)
426 : {
427 0 : GNUNET_break_op (0);
428 0 : return GNUNET_SYSERR;
429 : }
430 42 : if ( (fid > TALER_AMOUNT_FRAC_LEN) ||
431 42 : (fnd > TALER_AMOUNT_FRAC_LEN) ||
432 42 : (ftzd > TALER_AMOUNT_FRAC_LEN) )
433 : {
434 0 : GNUNET_break_op (0);
435 0 : return GNUNET_SYSERR;
436 : }
437 42 : if (GNUNET_OK !=
438 42 : TALER_check_currency (currency))
439 : {
440 0 : GNUNET_break_op (0);
441 0 : return GNUNET_SYSERR;
442 : }
443 42 : strcpy (r_cspec->currency,
444 : currency);
445 42 : if (GNUNET_OK !=
446 42 : TALER_check_currency_scale_map (map))
447 : {
448 0 : GNUNET_break_op (0);
449 0 : return GNUNET_SYSERR;
450 : }
451 42 : r_cspec->name = GNUNET_strdup (name);
452 42 : r_cspec->map_alt_unit_names = json_incref ((json_t *) map);
453 42 : if (NULL != ca)
454 : {
455 : size_t i;
456 : json_t *v;
457 :
458 210 : json_array_foreach ((json_t *) ca, i, v)
459 : {
460 : struct TALER_Amount val;
461 : const char *vstr;
462 :
463 168 : vstr = json_string_value (v);
464 336 : if ( (NULL == vstr) ||
465 : (GNUNET_OK !=
466 168 : TALER_string_to_amount (vstr,
467 : &val)) )
468 : {
469 0 : GNUNET_break_op (0);
470 0 : return GNUNET_SYSERR;
471 : }
472 168 : if (0 != strcasecmp (val.currency,
473 168 : r_cspec->currency))
474 : {
475 0 : GNUNET_break_op (0);
476 0 : return GNUNET_SYSERR;
477 : }
478 168 : GNUNET_array_append (r_cspec->common_amounts,
479 : r_cspec->num_common_amounts,
480 : val);
481 : }
482 : }
483 42 : return GNUNET_OK;
484 : }
485 :
486 :
487 : /**
488 : * Cleanup data left from parsing encrypted contract.
489 : *
490 : * @param cls closure, NULL
491 : * @param[out] spec where to free the data
492 : */
493 : static void
494 0 : clean_cspec (void *cls,
495 : struct GNUNET_JSON_Specification *spec)
496 : {
497 0 : struct TALER_CurrencySpecification *cspec = spec->ptr;
498 :
499 : (void) cls;
500 0 : GNUNET_array_grow (cspec->common_amounts,
501 : cspec->num_common_amounts,
502 : 0);
503 0 : GNUNET_free (cspec->name);
504 0 : json_decref (cspec->map_alt_unit_names);
505 0 : }
506 :
507 :
508 : struct GNUNET_JSON_Specification
509 42 : TALER_JSON_spec_currency_specification (
510 : const char *name,
511 : const char *currency,
512 : struct TALER_CurrencySpecification *r_cspec)
513 : {
514 42 : struct GNUNET_JSON_Specification ret = {
515 : .parser = &parse_cspec,
516 : .cleaner = &clean_cspec,
517 : .cls = (void *) currency,
518 : .field = name,
519 : .ptr = r_cspec,
520 : .ptr_size = sizeof (*r_cspec),
521 : .size_ptr = NULL
522 : };
523 :
524 42 : memset (r_cspec,
525 : 0,
526 : sizeof (*r_cspec));
527 42 : return ret;
528 : }
529 :
530 :
531 : static enum GNUNET_GenericReturnValue
532 309 : parse_denomination_group (void *cls,
533 : json_t *root,
534 : struct GNUNET_JSON_Specification *spec)
535 : {
536 309 : struct TALER_DenominationGroup *group = spec->ptr;
537 : const char *cipher;
538 309 : const char *currency = cls;
539 309 : bool age_mask_missing = false;
540 309 : bool has_age_restricted_suffix = false;
541 : struct GNUNET_JSON_Specification gspec[] = {
542 309 : GNUNET_JSON_spec_string ("cipher",
543 : &cipher),
544 309 : TALER_JSON_spec_amount ("value",
545 : currency,
546 : &group->value),
547 309 : TALER_JSON_SPEC_DENOM_FEES ("fee",
548 : currency,
549 : &group->fees),
550 309 : GNUNET_JSON_spec_mark_optional (
551 : GNUNET_JSON_spec_uint32 ("age_mask",
552 : &group->age_mask.bits),
553 : &age_mask_missing),
554 309 : GNUNET_JSON_spec_end ()
555 : };
556 : const char *emsg;
557 : unsigned int eline;
558 :
559 309 : if (GNUNET_OK !=
560 309 : GNUNET_JSON_parse (root,
561 : gspec,
562 : &emsg,
563 : &eline))
564 : {
565 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
566 : "Failed to parse %s at %u: %s\n",
567 : gspec[eline].field,
568 : eline,
569 : emsg);
570 0 : GNUNET_break_op (0);
571 0 : return GNUNET_SYSERR;
572 : }
573 :
574 309 : group->cipher = string_to_cipher (cipher);
575 309 : if (GNUNET_CRYPTO_BSA_INVALID == group->cipher)
576 : {
577 0 : GNUNET_break_op (0);
578 0 : return GNUNET_SYSERR;
579 : }
580 :
581 : /* age_mask and suffix must be consistent */
582 309 : has_age_restricted_suffix =
583 309 : (NULL != strstr (cipher, "+age_restricted"));
584 309 : if (has_age_restricted_suffix && age_mask_missing)
585 : {
586 0 : GNUNET_break_op (0);
587 0 : return GNUNET_SYSERR;
588 : }
589 :
590 309 : if (age_mask_missing)
591 164 : group->age_mask.bits = 0;
592 :
593 309 : return GNUNET_OK;
594 : }
595 :
596 :
597 : struct GNUNET_JSON_Specification
598 309 : TALER_JSON_spec_denomination_group (const char *name,
599 : const char *currency,
600 : struct TALER_DenominationGroup *group)
601 : {
602 309 : struct GNUNET_JSON_Specification ret = {
603 : .cls = (void *) currency,
604 : .parser = &parse_denomination_group,
605 : .field = name,
606 : .ptr = group,
607 : .ptr_size = sizeof(*group)
608 : };
609 :
610 309 : return ret;
611 : }
612 :
613 :
614 : /**
615 : * Parse given JSON object to an encrypted contract.
616 : *
617 : * @param cls closure, NULL
618 : * @param root the json object representing data
619 : * @param[out] spec where to write the data
620 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
621 : */
622 : static enum GNUNET_GenericReturnValue
623 25 : parse_econtract (void *cls,
624 : json_t *root,
625 : struct GNUNET_JSON_Specification *spec)
626 : {
627 25 : struct TALER_EncryptedContract *econtract = spec->ptr;
628 : struct GNUNET_JSON_Specification ispec[] = {
629 25 : GNUNET_JSON_spec_varsize ("econtract",
630 : &econtract->econtract,
631 : &econtract->econtract_size),
632 25 : GNUNET_JSON_spec_fixed_auto ("econtract_sig",
633 : &econtract->econtract_sig),
634 25 : GNUNET_JSON_spec_fixed_auto ("contract_pub",
635 : &econtract->contract_pub),
636 25 : GNUNET_JSON_spec_end ()
637 : };
638 : const char *emsg;
639 : unsigned int eline;
640 :
641 : (void) cls;
642 25 : if (GNUNET_OK !=
643 25 : GNUNET_JSON_parse (root,
644 : ispec,
645 : &emsg,
646 : &eline))
647 : {
648 0 : GNUNET_break_op (0);
649 0 : return GNUNET_SYSERR;
650 : }
651 25 : return GNUNET_OK;
652 : }
653 :
654 :
655 : /**
656 : * Cleanup data left from parsing encrypted contract.
657 : *
658 : * @param cls closure, NULL
659 : * @param[out] spec where to free the data
660 : */
661 : static void
662 11 : clean_econtract (void *cls,
663 : struct GNUNET_JSON_Specification *spec)
664 : {
665 11 : struct TALER_EncryptedContract *econtract = spec->ptr;
666 :
667 : (void) cls;
668 11 : GNUNET_free (econtract->econtract);
669 11 : }
670 :
671 :
672 : struct GNUNET_JSON_Specification
673 25 : TALER_JSON_spec_econtract (const char *name,
674 : struct TALER_EncryptedContract *econtract)
675 : {
676 25 : struct GNUNET_JSON_Specification ret = {
677 : .parser = &parse_econtract,
678 : .cleaner = &clean_econtract,
679 : .field = name,
680 : .ptr = econtract
681 : };
682 :
683 25 : return ret;
684 : }
685 :
686 :
687 : /**
688 : * Parse given JSON object to an age commitmnet
689 : *
690 : * @param cls closure, NULL
691 : * @param root the json object representing data
692 : * @param[out] spec where to write the data
693 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
694 : */
695 : static enum GNUNET_GenericReturnValue
696 8 : parse_age_commitment (void *cls,
697 : json_t *root,
698 : struct GNUNET_JSON_Specification *spec)
699 : {
700 8 : struct TALER_AgeCommitment *age_commitment = spec->ptr;
701 : json_t *pk;
702 : unsigned int idx;
703 : size_t num;
704 :
705 : (void) cls;
706 8 : if ( (NULL == root) ||
707 8 : (! json_is_array (root)))
708 : {
709 0 : GNUNET_break_op (0);
710 0 : return GNUNET_SYSERR;
711 : }
712 :
713 8 : num = json_array_size (root);
714 8 : if (32 <= num || 0 == num)
715 : {
716 0 : GNUNET_break_op (0);
717 0 : return GNUNET_SYSERR;
718 : }
719 :
720 8 : age_commitment->num = num;
721 8 : age_commitment->pubs =
722 8 : GNUNET_new_array (num,
723 : struct TALER_AgeCommitmentPublicKeyP);
724 :
725 64 : json_array_foreach (root, idx, pk) {
726 : const char *emsg;
727 : unsigned int eline;
728 : struct GNUNET_JSON_Specification pkspec[] = {
729 56 : GNUNET_JSON_spec_fixed_auto (
730 : NULL,
731 : &age_commitment->pubs[idx].pub),
732 56 : GNUNET_JSON_spec_end ()
733 : };
734 :
735 56 : if (GNUNET_OK !=
736 56 : GNUNET_JSON_parse (pk,
737 : pkspec,
738 : &emsg,
739 : &eline))
740 : {
741 0 : GNUNET_break_op (0);
742 0 : GNUNET_free (age_commitment->pubs);
743 0 : age_commitment->num = 0;
744 0 : return GNUNET_SYSERR;
745 : }
746 : };
747 :
748 8 : return GNUNET_OK;
749 : }
750 :
751 :
752 : /**
753 : * Cleanup data left from parsing age commitment
754 : *
755 : * @param cls closure, NULL
756 : * @param[out] spec where to free the data
757 : */
758 : static void
759 14 : clean_age_commitment (void *cls,
760 : struct GNUNET_JSON_Specification *spec)
761 : {
762 14 : struct TALER_AgeCommitment *age_commitment = spec->ptr;
763 :
764 : (void) cls;
765 14 : if ( (NULL == age_commitment) ||
766 14 : (NULL == age_commitment->pubs) )
767 6 : return;
768 8 : age_commitment->num = 0;
769 8 : GNUNET_free (age_commitment->pubs);
770 : }
771 :
772 :
773 : struct GNUNET_JSON_Specification
774 34 : TALER_JSON_spec_age_commitment (const char *name,
775 : struct TALER_AgeCommitment *age_commitment)
776 : {
777 34 : struct GNUNET_JSON_Specification ret = {
778 : .parser = &parse_age_commitment,
779 : .cleaner = &clean_age_commitment,
780 : .field = name,
781 : .ptr = age_commitment
782 : };
783 :
784 34 : return ret;
785 : }
786 :
787 :
788 : struct GNUNET_JSON_Specification
789 0 : TALER_JSON_spec_token_issue_sig (const char *field,
790 : struct TALER_TokenIssueSignature *sig)
791 : {
792 0 : sig->signature = NULL;
793 0 : return GNUNET_JSON_spec_unblinded_signature (field,
794 : &sig->signature);
795 : }
796 :
797 :
798 : struct GNUNET_JSON_Specification
799 0 : TALER_JSON_spec_blinded_token_issue_sig (
800 : const char *field,
801 : struct TALER_BlindedTokenIssueSignature *sig)
802 : {
803 0 : sig->signature = NULL;
804 0 : return GNUNET_JSON_spec_blinded_signature (field,
805 : &sig->signature);
806 : }
807 :
808 :
809 : struct GNUNET_JSON_Specification
810 0 : TALER_JSON_spec_token_envelope (const char *field,
811 : struct TALER_TokenEnvelope *env)
812 : {
813 0 : env->blinded_pub = NULL;
814 0 : return GNUNET_JSON_spec_blinded_message (field,
815 : &env->blinded_pub);
816 : }
817 :
818 :
819 : /**
820 : * Parse given JSON object to denomination public key.
821 : *
822 : * @param cls closure, NULL
823 : * @param root the json object representing data
824 : * @param[out] spec where to write the data
825 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
826 : */
827 : static enum GNUNET_GenericReturnValue
828 706 : parse_denom_pub (void *cls,
829 : json_t *root,
830 : struct GNUNET_JSON_Specification *spec)
831 : {
832 706 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
833 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
834 : const char *cipher;
835 706 : bool age_mask_missing = false;
836 : struct GNUNET_JSON_Specification dspec[] = {
837 706 : GNUNET_JSON_spec_string ("cipher",
838 : &cipher),
839 706 : GNUNET_JSON_spec_mark_optional (
840 : GNUNET_JSON_spec_uint32 ("age_mask",
841 : &denom_pub->age_mask.bits),
842 : &age_mask_missing),
843 706 : GNUNET_JSON_spec_end ()
844 : };
845 : const char *emsg;
846 : unsigned int eline;
847 :
848 : (void) cls;
849 706 : if (GNUNET_OK !=
850 706 : GNUNET_JSON_parse (root,
851 : dspec,
852 : &emsg,
853 : &eline))
854 : {
855 0 : GNUNET_break_op (0);
856 0 : return GNUNET_SYSERR;
857 : }
858 :
859 706 : if (age_mask_missing)
860 0 : denom_pub->age_mask.bits = 0;
861 706 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
862 706 : bsign_pub->rc = 1;
863 706 : bsign_pub->cipher = string_to_cipher (cipher);
864 706 : switch (bsign_pub->cipher)
865 : {
866 0 : case GNUNET_CRYPTO_BSA_INVALID:
867 0 : break;
868 388 : case GNUNET_CRYPTO_BSA_RSA:
869 : {
870 : struct GNUNET_JSON_Specification ispec[] = {
871 388 : GNUNET_JSON_spec_rsa_public_key (
872 : "rsa_pub",
873 : &bsign_pub->details.rsa_public_key),
874 388 : GNUNET_JSON_spec_end ()
875 : };
876 :
877 388 : if (GNUNET_OK !=
878 388 : GNUNET_JSON_parse (root,
879 : ispec,
880 : &emsg,
881 : &eline))
882 : {
883 0 : GNUNET_break_op (0);
884 0 : GNUNET_free (bsign_pub);
885 0 : return GNUNET_SYSERR;
886 : }
887 388 : denom_pub->bsign_pub_key = bsign_pub;
888 388 : return GNUNET_OK;
889 : }
890 318 : case GNUNET_CRYPTO_BSA_CS:
891 : {
892 : struct GNUNET_JSON_Specification ispec[] = {
893 318 : GNUNET_JSON_spec_fixed ("cs_pub",
894 318 : &bsign_pub->details.cs_public_key,
895 : sizeof (bsign_pub->details.cs_public_key)),
896 318 : GNUNET_JSON_spec_end ()
897 : };
898 :
899 318 : if (GNUNET_OK !=
900 318 : GNUNET_JSON_parse (root,
901 : ispec,
902 : &emsg,
903 : &eline))
904 : {
905 0 : GNUNET_break_op (0);
906 0 : GNUNET_free (bsign_pub);
907 0 : return GNUNET_SYSERR;
908 : }
909 318 : denom_pub->bsign_pub_key = bsign_pub;
910 318 : return GNUNET_OK;
911 : }
912 : }
913 0 : GNUNET_break_op (0);
914 0 : GNUNET_free (bsign_pub);
915 0 : return GNUNET_SYSERR;
916 : }
917 :
918 :
919 : /**
920 : * Cleanup data left from parsing denomination public key.
921 : *
922 : * @param cls closure, NULL
923 : * @param[out] spec where to free the data
924 : */
925 : static void
926 533 : clean_denom_pub (void *cls,
927 : struct GNUNET_JSON_Specification *spec)
928 : {
929 533 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
930 :
931 : (void) cls;
932 533 : TALER_denom_pub_free (denom_pub);
933 533 : }
934 :
935 :
936 : struct GNUNET_JSON_Specification
937 706 : TALER_JSON_spec_denom_pub (const char *field,
938 : struct TALER_DenominationPublicKey *pk)
939 : {
940 706 : struct GNUNET_JSON_Specification ret = {
941 : .parser = &parse_denom_pub,
942 : .cleaner = &clean_denom_pub,
943 : .field = field,
944 : .ptr = pk
945 : };
946 :
947 706 : pk->bsign_pub_key = NULL;
948 706 : return ret;
949 : }
950 :
951 :
952 : /**
953 : * Parse given JSON object to token issue public key.
954 : *
955 : * @param cls closure, NULL
956 : * @param root the json object representing data
957 : * @param[out] spec where to write the data
958 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
959 : */
960 : static enum GNUNET_GenericReturnValue
961 0 : parse_token_pub (void *cls,
962 : json_t *root,
963 : struct GNUNET_JSON_Specification *spec)
964 : {
965 0 : struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
966 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
967 : const char *cipher;
968 : struct GNUNET_JSON_Specification dspec[] = {
969 0 : GNUNET_JSON_spec_string ("cipher",
970 : &cipher),
971 0 : GNUNET_JSON_spec_end ()
972 : };
973 : const char *emsg;
974 : unsigned int eline;
975 :
976 : (void) cls;
977 0 : if (GNUNET_OK !=
978 0 : GNUNET_JSON_parse (root,
979 : dspec,
980 : &emsg,
981 : &eline))
982 : {
983 0 : GNUNET_break_op (0);
984 0 : return GNUNET_SYSERR;
985 : }
986 :
987 0 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
988 0 : bsign_pub->rc = 1;
989 0 : bsign_pub->cipher = string_to_cipher (cipher);
990 0 : switch (bsign_pub->cipher)
991 : {
992 0 : case GNUNET_CRYPTO_BSA_INVALID:
993 0 : break;
994 0 : case GNUNET_CRYPTO_BSA_RSA:
995 : {
996 : struct GNUNET_JSON_Specification ispec[] = {
997 0 : GNUNET_JSON_spec_rsa_public_key (
998 : "rsa_pub",
999 : &bsign_pub->details.rsa_public_key),
1000 0 : GNUNET_JSON_spec_end ()
1001 : };
1002 :
1003 0 : if (GNUNET_OK !=
1004 0 : GNUNET_JSON_parse (root,
1005 : ispec,
1006 : &emsg,
1007 : &eline))
1008 : {
1009 0 : GNUNET_break_op (0);
1010 0 : GNUNET_free (bsign_pub);
1011 0 : return GNUNET_SYSERR;
1012 : }
1013 0 : GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key,
1014 : &bsign_pub->pub_key_hash);
1015 0 : token_pub->public_key = bsign_pub;
1016 0 : return GNUNET_OK;
1017 : }
1018 0 : case GNUNET_CRYPTO_BSA_CS:
1019 : {
1020 : struct GNUNET_JSON_Specification ispec[] = {
1021 0 : GNUNET_JSON_spec_fixed ("cs_pub",
1022 0 : &bsign_pub->details.cs_public_key,
1023 : sizeof (bsign_pub->details.cs_public_key)),
1024 0 : GNUNET_JSON_spec_end ()
1025 : };
1026 :
1027 0 : if (GNUNET_OK !=
1028 0 : GNUNET_JSON_parse (root,
1029 : ispec,
1030 : &emsg,
1031 : &eline))
1032 : {
1033 0 : GNUNET_break_op (0);
1034 0 : GNUNET_free (bsign_pub);
1035 0 : return GNUNET_SYSERR;
1036 : }
1037 0 : GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
1038 : sizeof(bsign_pub->details.cs_public_key),
1039 : &bsign_pub->pub_key_hash);
1040 0 : token_pub->public_key = bsign_pub;
1041 0 : return GNUNET_OK;
1042 : }
1043 : }
1044 0 : GNUNET_break_op (0);
1045 0 : GNUNET_free (bsign_pub);
1046 0 : return GNUNET_SYSERR;
1047 : }
1048 :
1049 :
1050 : /**
1051 : * Cleanup data left from parsing token issue public key.
1052 : *
1053 : * @param cls closure, NULL
1054 : * @param[out] spec where to free the data
1055 : */
1056 : static void
1057 0 : clean_token_pub (void *cls,
1058 : struct GNUNET_JSON_Specification *spec)
1059 : {
1060 0 : struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
1061 :
1062 : (void) cls;
1063 0 : TALER_token_issue_pub_free (token_pub);
1064 0 : }
1065 :
1066 :
1067 : struct GNUNET_JSON_Specification
1068 0 : TALER_JSON_spec_token_pub (const char *field,
1069 : struct TALER_TokenIssuePublicKey *pk)
1070 : {
1071 0 : struct GNUNET_JSON_Specification ret = {
1072 : .field = field,
1073 : .parser = &parse_token_pub,
1074 : .cleaner = &clean_token_pub,
1075 : .ptr = pk
1076 : };
1077 :
1078 0 : pk->public_key = NULL;
1079 0 : return ret;
1080 : }
1081 :
1082 :
1083 : /**
1084 : * Parse given JSON object partially into a denomination public key.
1085 : *
1086 : * Depending on the cipher in cls, it parses the corresponding public key type.
1087 : *
1088 : * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm
1089 : * @param root the json object representing data
1090 : * @param[out] spec where to write the data
1091 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1092 : */
1093 : static enum GNUNET_GenericReturnValue
1094 890 : parse_denom_pub_cipher (void *cls,
1095 : json_t *root,
1096 : struct GNUNET_JSON_Specification *spec)
1097 : {
1098 890 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
1099 890 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher =
1100 890 : (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls;
1101 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
1102 : const char *emsg;
1103 : unsigned int eline;
1104 :
1105 890 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
1106 890 : bsign_pub->cipher = cipher;
1107 890 : bsign_pub->rc = 1;
1108 890 : switch (cipher)
1109 : {
1110 0 : case GNUNET_CRYPTO_BSA_INVALID:
1111 0 : break;
1112 460 : case GNUNET_CRYPTO_BSA_RSA:
1113 : {
1114 : struct GNUNET_JSON_Specification ispec[] = {
1115 460 : GNUNET_JSON_spec_rsa_public_key (
1116 : "rsa_pub",
1117 : &bsign_pub->details.rsa_public_key),
1118 460 : GNUNET_JSON_spec_end ()
1119 : };
1120 :
1121 460 : if (GNUNET_OK !=
1122 460 : GNUNET_JSON_parse (root,
1123 : ispec,
1124 : &emsg,
1125 : &eline))
1126 : {
1127 0 : GNUNET_break_op (0);
1128 0 : GNUNET_free (bsign_pub);
1129 0 : return GNUNET_SYSERR;
1130 : }
1131 460 : denom_pub->bsign_pub_key = bsign_pub;
1132 460 : return GNUNET_OK;
1133 : }
1134 430 : case GNUNET_CRYPTO_BSA_CS:
1135 : {
1136 : struct GNUNET_JSON_Specification ispec[] = {
1137 430 : GNUNET_JSON_spec_fixed ("cs_pub",
1138 430 : &bsign_pub->details.cs_public_key,
1139 : sizeof (bsign_pub->details.cs_public_key)),
1140 430 : GNUNET_JSON_spec_end ()
1141 : };
1142 :
1143 430 : if (GNUNET_OK !=
1144 430 : GNUNET_JSON_parse (root,
1145 : ispec,
1146 : &emsg,
1147 : &eline))
1148 : {
1149 0 : GNUNET_break_op (0);
1150 0 : GNUNET_free (bsign_pub);
1151 0 : return GNUNET_SYSERR;
1152 : }
1153 430 : denom_pub->bsign_pub_key = bsign_pub;
1154 430 : return GNUNET_OK;
1155 : }
1156 : }
1157 0 : GNUNET_break_op (0);
1158 0 : GNUNET_free (bsign_pub);
1159 0 : return GNUNET_SYSERR;
1160 : }
1161 :
1162 :
1163 : struct GNUNET_JSON_Specification
1164 890 : TALER_JSON_spec_denom_pub_cipher (
1165 : const char *field,
1166 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
1167 : struct TALER_DenominationPublicKey *pk)
1168 : {
1169 890 : struct GNUNET_JSON_Specification ret = {
1170 : .parser = &parse_denom_pub_cipher,
1171 : .cleaner = &clean_denom_pub,
1172 : .field = field,
1173 890 : .cls = (void *) cipher,
1174 : .ptr = pk
1175 : };
1176 :
1177 890 : pk->bsign_pub_key = NULL;
1178 890 : return ret;
1179 : }
1180 :
1181 :
1182 : struct GNUNET_JSON_Specification
1183 150 : TALER_JSON_spec_denom_sig (const char *field,
1184 : struct TALER_DenominationSignature *sig)
1185 : {
1186 150 : sig->unblinded_sig = NULL;
1187 150 : return GNUNET_JSON_spec_unblinded_signature (field,
1188 : &sig->unblinded_sig);
1189 : }
1190 :
1191 :
1192 : struct GNUNET_JSON_Specification
1193 126 : TALER_JSON_spec_blinded_denom_sig (
1194 : const char *field,
1195 : struct TALER_BlindedDenominationSignature *sig)
1196 : {
1197 126 : sig->blinded_sig = NULL;
1198 126 : return GNUNET_JSON_spec_blinded_signature (field,
1199 : &sig->blinded_sig);
1200 : }
1201 :
1202 :
1203 : struct GNUNET_JSON_Specification
1204 459 : TALER_JSON_spec_blinded_planchet (
1205 : const char *field,
1206 : struct TALER_BlindedPlanchet *blinded_planchet)
1207 : {
1208 459 : blinded_planchet->blinded_message = NULL;
1209 459 : return GNUNET_JSON_spec_blinded_message (field,
1210 : &blinded_planchet->blinded_message);
1211 : }
1212 :
1213 :
1214 : /**
1215 : * Parse given JSON object to exchange withdraw values (/csr).
1216 : *
1217 : * @param cls closure, NULL
1218 : * @param root the json object representing data
1219 : * @param[out] spec where to write the data
1220 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1221 : */
1222 : static enum GNUNET_GenericReturnValue
1223 0 : parse_exchange_blinding_values (void *cls,
1224 : json_t *root,
1225 : struct GNUNET_JSON_Specification *spec)
1226 : {
1227 0 : struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
1228 : struct GNUNET_CRYPTO_BlindingInputValues *bi;
1229 : const char *cipher;
1230 : struct GNUNET_JSON_Specification dspec[] = {
1231 0 : GNUNET_JSON_spec_string ("cipher",
1232 : &cipher),
1233 0 : GNUNET_JSON_spec_end ()
1234 : };
1235 : const char *emsg;
1236 : unsigned int eline;
1237 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm ci;
1238 :
1239 : (void) cls;
1240 0 : if (GNUNET_OK !=
1241 0 : GNUNET_JSON_parse (root,
1242 : dspec,
1243 : &emsg,
1244 : &eline))
1245 : {
1246 0 : GNUNET_break_op (0);
1247 0 : return GNUNET_SYSERR;
1248 : }
1249 0 : ci = string_to_cipher (cipher);
1250 0 : switch (ci)
1251 : {
1252 0 : case GNUNET_CRYPTO_BSA_INVALID:
1253 0 : break;
1254 0 : case GNUNET_CRYPTO_BSA_RSA:
1255 0 : ewv->blinding_inputs = TALER_denom_ewv_rsa_singleton ()->blinding_inputs;
1256 0 : return GNUNET_OK;
1257 0 : case GNUNET_CRYPTO_BSA_CS:
1258 0 : bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
1259 0 : bi->cipher = GNUNET_CRYPTO_BSA_CS;
1260 0 : bi->rc = 1;
1261 : {
1262 : struct GNUNET_JSON_Specification ispec[] = {
1263 0 : GNUNET_JSON_spec_fixed (
1264 : "r_pub_0",
1265 0 : &bi->details.cs_values.r_pub[0],
1266 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1267 0 : GNUNET_JSON_spec_fixed (
1268 : "r_pub_1",
1269 0 : &bi->details.cs_values.r_pub[1],
1270 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1271 0 : GNUNET_JSON_spec_end ()
1272 : };
1273 :
1274 0 : if (GNUNET_OK !=
1275 0 : GNUNET_JSON_parse (root,
1276 : ispec,
1277 : &emsg,
1278 : &eline))
1279 : {
1280 0 : GNUNET_break_op (0);
1281 0 : GNUNET_free (bi);
1282 0 : return GNUNET_SYSERR;
1283 : }
1284 0 : ewv->blinding_inputs = bi;
1285 0 : return GNUNET_OK;
1286 : }
1287 : }
1288 0 : GNUNET_break_op (0);
1289 0 : return GNUNET_SYSERR;
1290 : }
1291 :
1292 :
1293 : /**
1294 : * Cleanup data left from parsing withdraw values
1295 : *
1296 : * @param cls closure, NULL
1297 : * @param[out] spec where to free the data
1298 : */
1299 : static void
1300 0 : clean_exchange_blinding_values (
1301 : void *cls,
1302 : struct GNUNET_JSON_Specification *spec)
1303 : {
1304 0 : struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
1305 :
1306 : (void) cls;
1307 0 : TALER_denom_ewv_free (ewv);
1308 0 : }
1309 :
1310 :
1311 : struct GNUNET_JSON_Specification
1312 0 : TALER_JSON_spec_exchange_blinding_values (
1313 : const char *field,
1314 : struct TALER_ExchangeBlindingValues *ewv)
1315 : {
1316 0 : struct GNUNET_JSON_Specification ret = {
1317 : .parser = &parse_exchange_blinding_values,
1318 : .cleaner = &clean_exchange_blinding_values,
1319 : .field = field,
1320 : .ptr = ewv
1321 : };
1322 :
1323 0 : ewv->blinding_inputs = NULL;
1324 0 : return ret;
1325 : }
1326 :
1327 :
1328 : /**
1329 : * Closure for #parse_i18n_string.
1330 : */
1331 : struct I18nContext
1332 : {
1333 : /**
1334 : * Language pattern to match.
1335 : */
1336 : char *lp;
1337 :
1338 : /**
1339 : * Name of the field to match.
1340 : */
1341 : const char *field;
1342 : };
1343 :
1344 :
1345 : /**
1346 : * Parse given JSON object to internationalized string.
1347 : *
1348 : * @param cls closure, our `struct I18nContext *`
1349 : * @param root the json object representing data
1350 : * @param[out] spec where to write the data
1351 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1352 : */
1353 : static enum GNUNET_GenericReturnValue
1354 0 : parse_i18n_string (void *cls,
1355 : json_t *root,
1356 : struct GNUNET_JSON_Specification *spec)
1357 : {
1358 0 : struct I18nContext *ctx = cls;
1359 : json_t *i18n;
1360 : json_t *val;
1361 :
1362 : {
1363 : char *i18nf;
1364 :
1365 0 : GNUNET_asprintf (&i18nf,
1366 : "%s_i18n",
1367 : ctx->field);
1368 0 : i18n = json_object_get (root,
1369 : i18nf);
1370 0 : GNUNET_free (i18nf);
1371 : }
1372 :
1373 0 : val = json_object_get (root,
1374 : ctx->field);
1375 0 : if ( (NULL != i18n) &&
1376 0 : (NULL != ctx->lp) )
1377 : {
1378 0 : double best = 0.0;
1379 : json_t *pos;
1380 : const char *lang;
1381 :
1382 0 : json_object_foreach (i18n, lang, pos)
1383 : {
1384 : double score;
1385 :
1386 0 : score = TALER_pattern_matches (ctx->lp,
1387 : lang);
1388 0 : if (score > best)
1389 : {
1390 0 : best = score;
1391 0 : val = pos;
1392 : }
1393 : }
1394 : }
1395 :
1396 : {
1397 : const char *str;
1398 :
1399 0 : str = json_string_value (val);
1400 0 : *(const char **) spec->ptr = str;
1401 : }
1402 0 : return GNUNET_OK;
1403 : }
1404 :
1405 :
1406 : /**
1407 : * Function called to clean up data from earlier parsing.
1408 : *
1409 : * @param cls closure
1410 : * @param spec our specification entry with data to clean.
1411 : */
1412 : static void
1413 0 : i18n_cleaner (void *cls,
1414 : struct GNUNET_JSON_Specification *spec)
1415 : {
1416 0 : struct I18nContext *ctx = cls;
1417 :
1418 : (void) spec;
1419 0 : if (NULL != ctx)
1420 : {
1421 0 : GNUNET_free (ctx->lp);
1422 0 : GNUNET_free (ctx);
1423 : }
1424 0 : }
1425 :
1426 :
1427 : struct GNUNET_JSON_Specification
1428 0 : TALER_JSON_spec_i18n_string (const char *name,
1429 : const char *language_pattern,
1430 : const char **strptr)
1431 : {
1432 0 : struct I18nContext *ctx = GNUNET_new (struct I18nContext);
1433 0 : struct GNUNET_JSON_Specification ret = {
1434 : .parser = &parse_i18n_string,
1435 : .cleaner = &i18n_cleaner,
1436 : .cls = ctx,
1437 : .field = NULL, /* we want the main object */
1438 : .ptr = strptr,
1439 : .ptr_size = 0,
1440 : .size_ptr = NULL
1441 : };
1442 :
1443 0 : ctx->lp = (NULL != language_pattern)
1444 0 : ? GNUNET_strdup (language_pattern)
1445 0 : : NULL;
1446 0 : ctx->field = name;
1447 0 : *strptr = NULL;
1448 0 : return ret;
1449 : }
1450 :
1451 :
1452 : struct GNUNET_JSON_Specification
1453 0 : TALER_JSON_spec_i18n_str (const char *name,
1454 : const char **strptr)
1455 : {
1456 0 : const char *lang = getenv ("LANG");
1457 : const char *dot;
1458 : char *l;
1459 : struct GNUNET_JSON_Specification ret;
1460 :
1461 0 : if (NULL != lang)
1462 : {
1463 0 : dot = strchr (lang,
1464 : '.');
1465 0 : if (NULL == dot)
1466 0 : l = GNUNET_strdup (lang);
1467 : else
1468 0 : l = GNUNET_strndup (lang,
1469 : dot - lang);
1470 : }
1471 : else
1472 : {
1473 0 : l = NULL;
1474 : }
1475 0 : ret = TALER_JSON_spec_i18n_string (name,
1476 : l,
1477 : strptr);
1478 0 : GNUNET_free (l);
1479 0 : return ret;
1480 : }
1481 :
1482 :
1483 : /**
1484 : * Parse given JSON object with Taler error code.
1485 : *
1486 : * @param cls closure, NULL
1487 : * @param root the json object representing data
1488 : * @param[out] spec where to write the data
1489 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1490 : */
1491 : static enum GNUNET_GenericReturnValue
1492 0 : parse_ec (void *cls,
1493 : json_t *root,
1494 : struct GNUNET_JSON_Specification *spec)
1495 : {
1496 0 : enum TALER_ErrorCode *ec = spec->ptr;
1497 : json_int_t num;
1498 :
1499 : (void) cls;
1500 0 : if (! json_is_integer (root))
1501 : {
1502 0 : GNUNET_break_op (0);
1503 0 : return GNUNET_SYSERR;
1504 : }
1505 0 : num = json_integer_value (root);
1506 0 : if (num < 0)
1507 : {
1508 0 : GNUNET_break_op (0);
1509 0 : *ec = TALER_EC_INVALID;
1510 0 : return GNUNET_SYSERR;
1511 : }
1512 0 : *ec = (enum TALER_ErrorCode) num;
1513 0 : return GNUNET_OK;
1514 : }
1515 :
1516 :
1517 : struct GNUNET_JSON_Specification
1518 0 : TALER_JSON_spec_ec (const char *field,
1519 : enum TALER_ErrorCode *ec)
1520 : {
1521 0 : struct GNUNET_JSON_Specification ret = {
1522 : .parser = &parse_ec,
1523 : .field = field,
1524 : .ptr = ec
1525 : };
1526 :
1527 0 : *ec = TALER_EC_NONE;
1528 0 : return ret;
1529 : }
1530 :
1531 :
1532 : /**
1533 : * Parse given JSON object to web URL.
1534 : *
1535 : * @param cls closure, NULL
1536 : * @param root the json object representing data
1537 : * @param[out] spec where to write the data
1538 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1539 : */
1540 : static enum GNUNET_GenericReturnValue
1541 105 : parse_web_url (void *cls,
1542 : json_t *root,
1543 : struct GNUNET_JSON_Specification *spec)
1544 : {
1545 : const char *str;
1546 :
1547 : (void) cls;
1548 105 : str = json_string_value (root);
1549 105 : if (NULL == str)
1550 : {
1551 0 : GNUNET_break_op (0);
1552 0 : return GNUNET_SYSERR;
1553 : }
1554 105 : if (! TALER_is_web_url (str))
1555 : {
1556 0 : GNUNET_break_op (0);
1557 0 : return GNUNET_SYSERR;
1558 : }
1559 105 : *(const char **) spec->ptr = str;
1560 105 : return GNUNET_OK;
1561 : }
1562 :
1563 :
1564 : struct GNUNET_JSON_Specification
1565 497 : TALER_JSON_spec_web_url (const char *field,
1566 : const char **url)
1567 : {
1568 497 : struct GNUNET_JSON_Specification ret = {
1569 : .parser = &parse_web_url,
1570 : .field = field,
1571 : .ptr = url
1572 : };
1573 :
1574 497 : *url = NULL;
1575 497 : return ret;
1576 : }
1577 :
1578 :
1579 : /**
1580 : * Parse given JSON object to web URL, and make a copy.
1581 : *
1582 : * @param cls closure, NULL
1583 : * @param root the json object representing data
1584 : * @param[out] spec where to write the data
1585 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1586 : */
1587 : static enum GNUNET_GenericReturnValue
1588 0 : parse_web_url_copy (void *cls,
1589 : json_t *root,
1590 : struct GNUNET_JSON_Specification *spec)
1591 : {
1592 : const char *str;
1593 :
1594 : (void) cls;
1595 0 : str = json_string_value (root);
1596 0 : if (NULL == str)
1597 : {
1598 0 : GNUNET_break_op (0);
1599 0 : return GNUNET_SYSERR;
1600 : }
1601 0 : if (! TALER_is_web_url (str))
1602 : {
1603 0 : GNUNET_break_op (0);
1604 0 : return GNUNET_SYSERR;
1605 : }
1606 0 : *(char **) spec->ptr = GNUNET_strdup (str);
1607 0 : return GNUNET_OK;
1608 : }
1609 :
1610 :
1611 : struct GNUNET_JSON_Specification
1612 0 : TALER_JSON_spec_web_url_copy (const char *field,
1613 : char **url)
1614 : {
1615 0 : struct GNUNET_JSON_Specification ret = {
1616 : .parser = &parse_web_url_copy,
1617 : .field = field,
1618 : .ptr = url
1619 : };
1620 :
1621 0 : *url = NULL;
1622 0 : return ret;
1623 : }
1624 :
1625 :
1626 : /**
1627 : * Parse given JSON object to slug.
1628 : *
1629 : * @param cls closure, NULL
1630 : * @param root the json object representing data
1631 : * @param[out] spec where to write the data
1632 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1633 : */
1634 : static enum GNUNET_GenericReturnValue
1635 14 : parse_slug (void *cls,
1636 : json_t *root,
1637 : struct GNUNET_JSON_Specification *spec)
1638 : {
1639 : const char *str;
1640 :
1641 : (void) cls;
1642 14 : str = json_string_value (root);
1643 14 : if (NULL == str)
1644 : {
1645 0 : GNUNET_break_op (0);
1646 0 : return GNUNET_SYSERR;
1647 : }
1648 14 : if (! TALER_is_slug (str))
1649 : {
1650 0 : GNUNET_break_op (0);
1651 0 : return GNUNET_SYSERR;
1652 : }
1653 14 : *(const char **) spec->ptr = str;
1654 14 : return GNUNET_OK;
1655 : }
1656 :
1657 :
1658 : struct GNUNET_JSON_Specification
1659 14 : TALER_JSON_spec_slug (const char *field,
1660 : const char **slug)
1661 : {
1662 14 : struct GNUNET_JSON_Specification ret = {
1663 : .parser = &parse_slug,
1664 : .field = field,
1665 : .ptr = slug
1666 : };
1667 :
1668 14 : *slug = NULL;
1669 14 : return ret;
1670 : }
1671 :
1672 :
1673 : /**
1674 : * Parse given JSON object to slug.
1675 : *
1676 : * @param cls closure, NULL
1677 : * @param root the json object representing data
1678 : * @param[out] spec where to write the data
1679 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1680 : */
1681 : static enum GNUNET_GenericReturnValue
1682 0 : parse_slug_copy (void *cls,
1683 : json_t *root,
1684 : struct GNUNET_JSON_Specification *spec)
1685 : {
1686 : const char *str;
1687 :
1688 : (void) cls;
1689 0 : str = json_string_value (root);
1690 0 : if (NULL == str)
1691 : {
1692 0 : GNUNET_break_op (0);
1693 0 : return GNUNET_SYSERR;
1694 : }
1695 0 : if (! TALER_is_slug (str))
1696 : {
1697 0 : GNUNET_break_op (0);
1698 0 : return GNUNET_SYSERR;
1699 : }
1700 0 : *(char **) spec->ptr = GNUNET_strdup (str);
1701 0 : return GNUNET_OK;
1702 : }
1703 :
1704 :
1705 : struct GNUNET_JSON_Specification
1706 0 : TALER_JSON_spec_slug_copy (const char *field,
1707 : char **slug)
1708 : {
1709 0 : struct GNUNET_JSON_Specification ret = {
1710 : .parser = &parse_slug_copy,
1711 : .field = field,
1712 : .ptr = slug
1713 : };
1714 :
1715 0 : *slug = NULL;
1716 0 : return ret;
1717 : }
1718 :
1719 :
1720 : /**
1721 : * Parse given JSON object to a session ID.
1722 : *
1723 : * @param cls closure, NULL
1724 : * @param root the json object representing data
1725 : * @param[out] spec where to write the data
1726 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1727 : */
1728 : static enum GNUNET_GenericReturnValue
1729 0 : parse_session_id (void *cls,
1730 : json_t *root,
1731 : struct GNUNET_JSON_Specification *spec)
1732 : {
1733 : const char *str;
1734 :
1735 : (void) cls;
1736 0 : str = json_string_value (root);
1737 0 : if (NULL == str)
1738 : {
1739 0 : GNUNET_break_op (0);
1740 0 : return GNUNET_SYSERR;
1741 : }
1742 0 : if (! TALER_is_session_id (str))
1743 : {
1744 0 : GNUNET_break_op (0);
1745 0 : return GNUNET_SYSERR;
1746 : }
1747 0 : *(const char **) spec->ptr = str;
1748 0 : return GNUNET_OK;
1749 : }
1750 :
1751 :
1752 : struct GNUNET_JSON_Specification
1753 0 : TALER_JSON_spec_session_id (const char *field,
1754 : const char **session_id)
1755 : {
1756 0 : struct GNUNET_JSON_Specification ret = {
1757 : .parser = &parse_session_id,
1758 : .field = field,
1759 : .ptr = session_id
1760 : };
1761 :
1762 0 : *session_id = NULL;
1763 0 : return ret;
1764 : }
1765 :
1766 :
1767 : /**
1768 : * Parse given JSON object to a session ID that must not be empty.
1769 : *
1770 : * @param cls closure, NULL
1771 : * @param root the json object representing data
1772 : * @param[out] spec where to write the data
1773 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1774 : */
1775 : static enum GNUNET_GenericReturnValue
1776 0 : parse_nonempty_session_id (void *cls,
1777 : json_t *root,
1778 : struct GNUNET_JSON_Specification *spec)
1779 : {
1780 0 : if (GNUNET_OK !=
1781 0 : parse_session_id (cls,
1782 : root,
1783 : spec))
1784 0 : return GNUNET_SYSERR;
1785 0 : if ('\0' == (*(const char **) spec->ptr)[0])
1786 : {
1787 0 : GNUNET_break_op (0);
1788 0 : return GNUNET_SYSERR;
1789 : }
1790 0 : return GNUNET_OK;
1791 : }
1792 :
1793 :
1794 : struct GNUNET_JSON_Specification
1795 0 : TALER_JSON_spec_nonempty_session_id (const char *field,
1796 : const char **session_id)
1797 : {
1798 0 : struct GNUNET_JSON_Specification ret = {
1799 : .parser = &parse_nonempty_session_id,
1800 : .field = field,
1801 : .ptr = session_id
1802 : };
1803 :
1804 0 : *session_id = NULL;
1805 0 : return ret;
1806 : }
1807 :
1808 :
1809 : /**
1810 : * Parse given JSON object to payto:// URI.
1811 : *
1812 : * @param cls closure, NULL
1813 : * @param root the json object representing data
1814 : * @param[out] spec where to write the data
1815 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1816 : */
1817 : static enum GNUNET_GenericReturnValue
1818 768 : parse_full_payto_uri (void *cls,
1819 : json_t *root,
1820 : struct GNUNET_JSON_Specification *spec)
1821 : {
1822 768 : struct TALER_FullPayto *payto_uri = spec->ptr;
1823 : const char *str;
1824 : char *err;
1825 :
1826 : (void) cls;
1827 768 : str = json_string_value (root);
1828 768 : if (NULL == str)
1829 : {
1830 0 : GNUNET_break_op (0);
1831 0 : return GNUNET_SYSERR;
1832 : }
1833 768 : payto_uri->full_payto = (char *) str;
1834 768 : err = TALER_payto_validate (*payto_uri);
1835 768 : if (NULL != err)
1836 : {
1837 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1838 : "payto:// malformed: %s\n",
1839 : err);
1840 0 : GNUNET_free (err);
1841 0 : payto_uri->full_payto = NULL;
1842 0 : return GNUNET_SYSERR;
1843 : }
1844 768 : return GNUNET_OK;
1845 : }
1846 :
1847 :
1848 : struct GNUNET_JSON_Specification
1849 770 : TALER_JSON_spec_full_payto_uri (
1850 : const char *field,
1851 : struct TALER_FullPayto *payto_uri)
1852 : {
1853 770 : struct GNUNET_JSON_Specification ret = {
1854 : .parser = &parse_full_payto_uri,
1855 : .field = field,
1856 : .ptr = payto_uri
1857 : };
1858 :
1859 770 : payto_uri->full_payto = NULL;
1860 770 : return ret;
1861 : }
1862 :
1863 :
1864 : /**
1865 : * Parse given JSON object to payto:// URI.
1866 : *
1867 : * @param cls closure, NULL
1868 : * @param root the json object representing data
1869 : * @param[out] spec where to write the data
1870 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1871 : */
1872 : static enum GNUNET_GenericReturnValue
1873 6 : parse_normalized_payto_uri (void *cls,
1874 : json_t *root,
1875 : struct GNUNET_JSON_Specification *spec)
1876 : {
1877 6 : struct TALER_NormalizedPayto *payto_uri = spec->ptr;
1878 : const char *str;
1879 :
1880 : (void) cls;
1881 6 : str = json_string_value (root);
1882 6 : if (NULL == str)
1883 : {
1884 0 : GNUNET_break_op (0);
1885 0 : return GNUNET_SYSERR;
1886 : }
1887 6 : payto_uri->normalized_payto = (char *) str;
1888 : {
1889 : char *err;
1890 :
1891 6 : err = TALER_normalized_payto_validate (*payto_uri);
1892 6 : if (NULL != err)
1893 : {
1894 0 : GNUNET_break_op (0);
1895 0 : GNUNET_free (err);
1896 0 : payto_uri->normalized_payto = NULL;
1897 0 : return GNUNET_SYSERR;
1898 : }
1899 : }
1900 6 : return GNUNET_OK;
1901 : }
1902 :
1903 :
1904 : struct GNUNET_JSON_Specification
1905 6 : TALER_JSON_spec_normalized_payto_uri (
1906 : const char *field,
1907 : struct TALER_NormalizedPayto *payto_uri)
1908 : {
1909 6 : struct GNUNET_JSON_Specification ret = {
1910 : .parser = &parse_normalized_payto_uri,
1911 : .field = field,
1912 : .ptr = payto_uri
1913 : };
1914 :
1915 6 : payto_uri->normalized_payto = NULL;
1916 6 : return ret;
1917 : }
1918 :
1919 :
1920 : /**
1921 : * Parse given JSON object with protocol version.
1922 : *
1923 : * @param cls closure, NULL
1924 : * @param root the json object representing data
1925 : * @param[out] spec where to write the data
1926 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1927 : */
1928 : static enum GNUNET_GenericReturnValue
1929 47 : parse_protocol_version (void *cls,
1930 : json_t *root,
1931 : struct GNUNET_JSON_Specification *spec)
1932 : {
1933 47 : struct TALER_JSON_ProtocolVersion *pv = spec->ptr;
1934 : const char *ver;
1935 : char dummy;
1936 :
1937 : (void) cls;
1938 47 : if (! json_is_string (root))
1939 : {
1940 0 : GNUNET_break_op (0);
1941 0 : return GNUNET_SYSERR;
1942 : }
1943 47 : ver = json_string_value (root);
1944 47 : if (3 != sscanf (ver,
1945 : "%u:%u:%u%c",
1946 : &pv->current,
1947 : &pv->revision,
1948 : &pv->age,
1949 : &dummy))
1950 : {
1951 0 : GNUNET_break_op (0);
1952 0 : return GNUNET_SYSERR;
1953 : }
1954 47 : return GNUNET_OK;
1955 : }
1956 :
1957 :
1958 : struct GNUNET_JSON_Specification
1959 47 : TALER_JSON_spec_version (const char *field,
1960 : struct TALER_JSON_ProtocolVersion *ver)
1961 : {
1962 47 : struct GNUNET_JSON_Specification ret = {
1963 : .parser = &parse_protocol_version,
1964 : .field = field,
1965 : .ptr = ver
1966 : };
1967 :
1968 47 : return ret;
1969 : }
1970 :
1971 :
1972 : /**
1973 : * Parse given JSON object to an OTP key.
1974 : *
1975 : * @param cls closure, NULL
1976 : * @param root the json object representing data
1977 : * @param[out] spec where to write the data
1978 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1979 : */
1980 : static enum GNUNET_GenericReturnValue
1981 0 : parse_otp_key (void *cls,
1982 : json_t *root,
1983 : struct GNUNET_JSON_Specification *spec)
1984 : {
1985 : const char *pos_key;
1986 :
1987 : (void) cls;
1988 0 : pos_key = json_string_value (root);
1989 0 : if (NULL == pos_key)
1990 : {
1991 0 : GNUNET_break_op (0);
1992 0 : return GNUNET_SYSERR;
1993 : }
1994 : {
1995 0 : size_t pos_key_length = strlen (pos_key);
1996 : void *key; /* pos_key in binary */
1997 : size_t key_len; /* length of the key */
1998 : int dret;
1999 :
2000 0 : key_len = pos_key_length * 5 / 8;
2001 0 : key = GNUNET_malloc (key_len);
2002 0 : dret = TALER_rfc3548_base32decode (pos_key,
2003 : pos_key_length,
2004 : key,
2005 : key_len);
2006 0 : if (-1 == dret)
2007 : {
2008 0 : GNUNET_free (key);
2009 0 : GNUNET_break_op (0);
2010 0 : return GNUNET_SYSERR;
2011 : }
2012 0 : GNUNET_free (key);
2013 : }
2014 0 : *(const char **) spec->ptr = pos_key;
2015 0 : return GNUNET_OK;
2016 : }
2017 :
2018 :
2019 : struct GNUNET_JSON_Specification
2020 0 : TALER_JSON_spec_otp_key (const char *name,
2021 : const char **otp_key)
2022 : {
2023 0 : struct GNUNET_JSON_Specification ret = {
2024 : .parser = &parse_otp_key,
2025 : .field = name,
2026 : .ptr = otp_key
2027 : };
2028 :
2029 0 : *otp_key = NULL;
2030 0 : return ret;
2031 : }
2032 :
2033 :
2034 : /**
2035 : * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm`
2036 : *
2037 : * @param cls closure, NULL
2038 : * @param root the json object representing data
2039 : * @param[out] spec where to write the data
2040 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
2041 : */
2042 : static enum GNUNET_GenericReturnValue
2043 0 : parse_otp_type (void *cls,
2044 : json_t *root,
2045 : struct GNUNET_JSON_Specification *spec)
2046 : {
2047 : static const struct Entry
2048 : {
2049 : const char *name;
2050 : enum TALER_MerchantConfirmationAlgorithm val;
2051 : } lt [] = {
2052 : { .name = "NONE",
2053 : .val = TALER_MCA_NONE },
2054 : { .name = "TOTP_WITHOUT_PRICE",
2055 : .val = TALER_MCA_WITHOUT_PRICE },
2056 : { .name = "TOTP_WITH_PRICE",
2057 : .val = TALER_MCA_WITH_PRICE },
2058 : { .name = "ECDSA_CHALLENGE",
2059 : .val = TALER_MCA_ECDSA_CHALLENGE },
2060 : { .name = "EDDSA_CHALLENGE",
2061 : .val = TALER_MCA_EDDSA_CHALLENGE },
2062 : { .name = NULL,
2063 : .val = TALER_MCA_NONE },
2064 : };
2065 0 : enum TALER_MerchantConfirmationAlgorithm *res
2066 : = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr;
2067 :
2068 : (void) cls;
2069 0 : if (json_is_string (root))
2070 : {
2071 : const char *str;
2072 :
2073 0 : str = json_string_value (root);
2074 0 : if (NULL == str)
2075 : {
2076 0 : GNUNET_break_op (0);
2077 0 : return GNUNET_SYSERR;
2078 : }
2079 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2080 : {
2081 0 : if (0 == strcasecmp (str,
2082 0 : lt[i].name))
2083 : {
2084 0 : *res = lt[i].val;
2085 0 : return GNUNET_OK;
2086 : }
2087 : }
2088 0 : GNUNET_break_op (0);
2089 : }
2090 0 : if (json_is_integer (root))
2091 : {
2092 : json_int_t val;
2093 :
2094 0 : val = json_integer_value (root);
2095 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2096 : {
2097 0 : if (val == lt[i].val)
2098 : {
2099 0 : *res = lt[i].val;
2100 0 : return GNUNET_OK;
2101 : }
2102 : }
2103 0 : GNUNET_break_op (0);
2104 0 : return GNUNET_SYSERR;
2105 : }
2106 0 : GNUNET_break_op (0);
2107 0 : return GNUNET_SYSERR;
2108 : }
2109 :
2110 :
2111 : struct GNUNET_JSON_Specification
2112 0 : TALER_JSON_spec_otp_type (const char *name,
2113 : enum TALER_MerchantConfirmationAlgorithm *mca)
2114 : {
2115 0 : struct GNUNET_JSON_Specification ret = {
2116 : .parser = &parse_otp_type,
2117 : .field = name,
2118 : .ptr = mca
2119 : };
2120 :
2121 0 : *mca = TALER_MCA_NONE;
2122 0 : return ret;
2123 : }
2124 :
2125 :
2126 : /**
2127 : * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent`
2128 : *
2129 : * @param cls closure, NULL
2130 : * @param root the json object representing data
2131 : * @param[out] spec where to write the data
2132 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
2133 : */
2134 : static enum GNUNET_GenericReturnValue
2135 334 : parse_kycte (void *cls,
2136 : json_t *root,
2137 : struct GNUNET_JSON_Specification *spec)
2138 : {
2139 : static const struct Entry
2140 : {
2141 : const char *name;
2142 : enum TALER_KYCLOGIC_KycTriggerEvent val;
2143 : } lt [] = {
2144 : { .name = "NONE",
2145 : .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
2146 : { .name = "WITHDRAW",
2147 : .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
2148 : { .name = "DEPOSIT",
2149 : .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
2150 : { .name = "MERGE",
2151 : .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
2152 : { .name = "BALANCE",
2153 : .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
2154 : { .name = "CLOSE",
2155 : .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
2156 : { .name = "AGGREGATE",
2157 : .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
2158 : { .name = "TRANSACTION",
2159 : .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
2160 : { .name = "REFUND",
2161 : .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
2162 : { .name = NULL,
2163 : .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
2164 : };
2165 334 : enum TALER_KYCLOGIC_KycTriggerEvent *res
2166 : = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr;
2167 :
2168 : (void) cls;
2169 334 : if (json_is_string (root))
2170 : {
2171 : const char *str;
2172 :
2173 334 : str = json_string_value (root);
2174 334 : if (NULL == str)
2175 : {
2176 0 : GNUNET_break_op (0);
2177 0 : return GNUNET_SYSERR;
2178 : }
2179 1545 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2180 : {
2181 1545 : if (0 == strcasecmp (str,
2182 1545 : lt[i].name))
2183 : {
2184 334 : *res = lt[i].val;
2185 334 : return GNUNET_OK;
2186 : }
2187 : }
2188 0 : GNUNET_break_op (0);
2189 0 : return GNUNET_SYSERR;
2190 : }
2191 0 : if (json_is_integer (root))
2192 : {
2193 : json_int_t val;
2194 :
2195 0 : val = json_integer_value (root);
2196 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2197 : {
2198 0 : if (val == lt[i].val)
2199 : {
2200 0 : *res = lt[i].val;
2201 0 : return GNUNET_OK;
2202 : }
2203 : }
2204 0 : GNUNET_break_op (0);
2205 0 : return GNUNET_SYSERR;
2206 : }
2207 0 : GNUNET_break_op (0);
2208 0 : return GNUNET_SYSERR;
2209 : }
2210 :
2211 :
2212 : struct GNUNET_JSON_Specification
2213 335 : TALER_JSON_spec_kycte (const char *name,
2214 : enum TALER_KYCLOGIC_KycTriggerEvent *kte)
2215 : {
2216 335 : struct GNUNET_JSON_Specification ret = {
2217 : .parser = &parse_kycte,
2218 : .field = name,
2219 : .ptr = kte
2220 : };
2221 :
2222 335 : *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE;
2223 335 : return ret;
2224 : }
2225 :
2226 :
2227 : /**
2228 : * Parser combinator of a tuple of parsers, for parsing
2229 : * an array of expected size and element types.
2230 : *
2231 : * @param cls closure, array of specs, NULL terminated
2232 : * @param root the json root
2233 : * @param[out] spec where to write the data
2234 : */
2235 : static enum GNUNET_GenericReturnValue
2236 115 : parse_tuple_of (void *cls,
2237 : json_t *root,
2238 : struct GNUNET_JSON_Specification *spec)
2239 : {
2240 115 : struct GNUNET_JSON_Specification *specs = cls;
2241 : static size_t max_specs = 100;
2242 115 : bool found_end = false;
2243 :
2244 : enum GNUNET_GenericReturnValue ret;
2245 :
2246 115 : if (! json_is_array (root))
2247 : {
2248 0 : return GNUNET_SYSERR;
2249 : }
2250 :
2251 : {
2252 : size_t num;
2253 345 : for (num = 0; num< max_specs; num++)
2254 : {
2255 345 : if (NULL == specs[num].parser)
2256 : {
2257 115 : found_end = true;
2258 115 : break;
2259 : }
2260 : }
2261 115 : GNUNET_assert (found_end);
2262 :
2263 115 : if (num != json_array_size (root))
2264 : {
2265 0 : GNUNET_break_op (0);
2266 0 : return GNUNET_SYSERR;
2267 : }
2268 : }
2269 :
2270 : {
2271 : json_t *j_entry;
2272 : size_t idx;
2273 :
2274 345 : json_array_foreach (root, idx, j_entry) {
2275 230 : ret = GNUNET_JSON_parse (j_entry,
2276 230 : &specs[idx],
2277 : NULL,
2278 : NULL);
2279 230 : if (GNUNET_OK != ret)
2280 : {
2281 0 : GNUNET_break_op (0);
2282 0 : return GNUNET_SYSERR;
2283 : }
2284 : }
2285 : }
2286 :
2287 115 : return GNUNET_OK;
2288 : }
2289 :
2290 :
2291 : struct GNUNET_JSON_Specification
2292 129 : TALER_JSON_spec_tuple_of (
2293 : const char *field,
2294 : struct GNUNET_JSON_Specification specs[])
2295 : {
2296 129 : struct GNUNET_JSON_Specification ret = {
2297 : .parser = &parse_tuple_of,
2298 : .field = field,
2299 : .cls = specs
2300 : };
2301 :
2302 129 : return ret;
2303 : }
2304 :
2305 :
2306 : /**
2307 : * Parser for an array of unknown length but
2308 : * of elements of the same type with the same
2309 : * fixed length.
2310 : *
2311 : * @param cls closure, entry_size
2312 : * @param root the json root
2313 : * @param spec the output spec
2314 : */
2315 : static enum GNUNET_GenericReturnValue
2316 90 : parse_array_fixed (void *cls,
2317 : json_t *root,
2318 : struct GNUNET_JSON_Specification *spec)
2319 : {
2320 : enum GNUNET_GenericReturnValue ret;
2321 90 : size_t entry_size = (size_t) cls;
2322 : size_t num_entries;
2323 :
2324 90 : GNUNET_assert (0< entry_size);
2325 90 : num_entries = spec->ptr_size / entry_size;
2326 90 : GNUNET_assert (0 < num_entries);
2327 :
2328 :
2329 90 : if (! json_is_array (root))
2330 : {
2331 0 : GNUNET_break_op (0);
2332 0 : return GNUNET_SYSERR;
2333 : }
2334 90 : if (num_entries != json_array_size (root))
2335 : {
2336 0 : GNUNET_break_op (0);
2337 0 : return GNUNET_SYSERR;
2338 : }
2339 :
2340 : {
2341 : json_t *j_entry;
2342 : size_t idx;
2343 90 : void *ptr = spec->ptr;
2344 90 : void *end = spec->ptr + spec->ptr_size;
2345 :
2346 450 : json_array_foreach (root, idx, j_entry) {
2347 : struct GNUNET_JSON_Specification esp[] = {
2348 360 : GNUNET_JSON_spec_fixed (NULL,
2349 : ptr,
2350 : entry_size),
2351 360 : GNUNET_JSON_spec_end ()
2352 : };
2353 360 : GNUNET_assert (ptr < end);
2354 360 : ret = GNUNET_JSON_parse (j_entry,
2355 : esp,
2356 : NULL,
2357 : NULL);
2358 360 : if (GNUNET_OK != ret)
2359 : {
2360 0 : GNUNET_break_op (0);
2361 0 : return GNUNET_SYSERR;
2362 : }
2363 360 : ptr += entry_size;
2364 : }
2365 : }
2366 90 : return GNUNET_OK;
2367 : }
2368 :
2369 :
2370 : struct GNUNET_JSON_Specification
2371 90 : TALER_JSON_spec_array_fixed (
2372 : const char *field,
2373 : size_t num_entries,
2374 : void *entries,
2375 : size_t entry_size)
2376 : {
2377 90 : struct GNUNET_JSON_Specification ret = {
2378 : .parser = &parse_array_fixed,
2379 : .ptr = entries,
2380 90 : .ptr_size = entry_size * num_entries,
2381 : .field = field,
2382 90 : .cls = (void *) entry_size,
2383 : };
2384 :
2385 90 : GNUNET_assert ((num_entries <= 1) ||
2386 : (entry_size * num_entries > entry_size));
2387 90 : return ret;
2388 : }
2389 :
2390 :
2391 : /**
2392 : * Closure for the parser of arrays of fixed size data
2393 : * of unknown array length
2394 : */
2395 : struct closure_array_of_data
2396 : {
2397 : /**
2398 : * Fixed (known) size per entry
2399 : */
2400 : size_t entry_size;
2401 :
2402 : /**
2403 : * Pointer where to put the number of elements
2404 : * allocated, i.e. the number of elements in the
2405 : * json array.
2406 : */
2407 : size_t *num_entries;
2408 : };
2409 :
2410 : /**
2411 : * Parser for an array of data of known element size,
2412 : * but unknown array length
2413 : */
2414 : static enum GNUNET_GenericReturnValue
2415 8 : parse_array_of_data (void *cls,
2416 : json_t *root,
2417 : struct GNUNET_JSON_Specification *spec)
2418 : {
2419 : enum GNUNET_GenericReturnValue ret;
2420 8 : struct closure_array_of_data *info = cls;
2421 : size_t num_entries;
2422 :
2423 8 : if (! json_is_array (root))
2424 : {
2425 0 : GNUNET_break_op (0);
2426 0 : return GNUNET_SYSERR;
2427 : }
2428 8 : num_entries = json_array_size (root);
2429 8 : *info->num_entries = num_entries;
2430 8 : if (0 == num_entries)
2431 : {
2432 0 : *(char **) spec->ptr = NULL;
2433 0 : return GNUNET_OK;
2434 : }
2435 :
2436 8 : spec->ptr_size = num_entries * info->entry_size;
2437 8 : GNUNET_assert (spec->ptr_size > num_entries);
2438 8 : *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size);
2439 :
2440 : {
2441 : json_t *j_entry;
2442 : size_t idx;
2443 8 : char *ptr = *(char **) spec->ptr;
2444 8 : char *end = ptr + spec->ptr_size;
2445 :
2446 25 : json_array_foreach (root, idx, j_entry) {
2447 : struct GNUNET_JSON_Specification esp[] = {
2448 17 : GNUNET_JSON_spec_fixed (NULL,
2449 : ptr,
2450 : info->entry_size),
2451 17 : GNUNET_JSON_spec_end ()
2452 : };
2453 17 : GNUNET_assert (ptr < end);
2454 17 : ret = GNUNET_JSON_parse (j_entry,
2455 : esp,
2456 : NULL,
2457 : NULL);
2458 17 : if (GNUNET_OK != ret)
2459 : {
2460 0 : GNUNET_break_op (0);
2461 0 : return GNUNET_SYSERR;
2462 : }
2463 17 : ptr += info->entry_size;
2464 : }
2465 : }
2466 8 : return GNUNET_OK;
2467 : }
2468 :
2469 :
2470 : /**
2471 : * Cleanup data left from parsing an array of fixed size (but unknown length).
2472 : *
2473 : * @param cls closure_of_array_data
2474 : * @param[out] spec where to free the data
2475 : */
2476 : static void
2477 7 : cleaner_array_of_data (void *cls,
2478 : struct GNUNET_JSON_Specification *spec)
2479 : {
2480 7 : struct closure_array_of_data *info = cls;
2481 :
2482 7 : GNUNET_free (*(void **) spec->ptr);
2483 7 : GNUNET_free (info);
2484 7 : }
2485 :
2486 :
2487 : struct GNUNET_JSON_Specification
2488 8 : TALER_JSON_spec_array_of_data (
2489 : const char *field,
2490 : size_t entry_size,
2491 : size_t *num_entries,
2492 : void **entries)
2493 : {
2494 : struct closure_array_of_data *cls;
2495 :
2496 8 : GNUNET_assert (0< entry_size);
2497 8 : *entries = NULL;
2498 8 : *num_entries = 0;
2499 8 : cls = GNUNET_new (struct closure_array_of_data);
2500 8 : cls->num_entries = num_entries;
2501 8 : cls->entry_size = entry_size;
2502 : {
2503 8 : struct GNUNET_JSON_Specification ret = {
2504 : .parser = &parse_array_of_data,
2505 : .ptr = entries,
2506 : .field = field,
2507 : .cleaner = &cleaner_array_of_data,
2508 : .cls = (void *) cls,
2509 : };
2510 :
2511 8 : return ret;
2512 : }
2513 : }
2514 :
2515 :
2516 : struct GNUNET_JSON_Specification
2517 7 : TALER_JSON_spec_array_of_denom_pub_h (
2518 : const char *field,
2519 : size_t *num_entries,
2520 : struct TALER_DenominationHashP **entries)
2521 : {
2522 7 : *num_entries = 0;
2523 7 : *entries = NULL;
2524 7 : return TALER_JSON_spec_array_of_data (
2525 : field,
2526 : sizeof (struct TALER_DenominationHashP),
2527 : num_entries,
2528 : (void **) entries);
2529 : }
2530 :
2531 :
2532 : /**
2533 : * Parser for an array of blinded denomination signatures,
2534 : * of unknown array length
2535 : */
2536 : static enum GNUNET_GenericReturnValue
2537 14 : parse_array_of_blinded_denom_sigs (void *cls,
2538 : json_t *root,
2539 : struct GNUNET_JSON_Specification *spec)
2540 : {
2541 : enum GNUNET_GenericReturnValue ret;
2542 14 : struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
2543 14 : size_t expected_num_entries = (size_t) cls;
2544 : size_t num_entries;
2545 :
2546 14 : if (! json_is_array (root))
2547 : {
2548 0 : GNUNET_break_op (0);
2549 0 : return GNUNET_SYSERR;
2550 : }
2551 14 : num_entries = json_array_size (root);
2552 14 : if (num_entries != expected_num_entries)
2553 : {
2554 0 : GNUNET_break_op (0);
2555 0 : return GNUNET_SYSERR;
2556 : }
2557 :
2558 : {
2559 : json_t *j_entry;
2560 : size_t idx;
2561 14 : struct TALER_BlindedDenominationSignature *ptr = sigs;
2562 :
2563 70 : json_array_foreach (root, idx, j_entry) {
2564 : struct GNUNET_JSON_Specification esp[] = {
2565 56 : TALER_JSON_spec_blinded_denom_sig (NULL,
2566 : ptr),
2567 56 : GNUNET_JSON_spec_end ()
2568 : };
2569 56 : ret = GNUNET_JSON_parse (j_entry,
2570 : esp,
2571 : NULL,
2572 : NULL);
2573 56 : if (GNUNET_OK != ret)
2574 : {
2575 0 : GNUNET_break_op (0);
2576 0 : for (size_t i = 0; i < idx; i++)
2577 : {
2578 0 : TALER_blinded_denom_sig_free (&sigs[i]);
2579 0 : sigs[i].blinded_sig = NULL;
2580 : }
2581 0 : return GNUNET_SYSERR;
2582 : }
2583 56 : ptr++;
2584 : }
2585 : }
2586 14 : return GNUNET_OK;
2587 : }
2588 :
2589 :
2590 : /**
2591 : * Cleanup data left from parsing an array of blinded signatures.
2592 : *
2593 : * @param cls pointer to a size_t with the length of the array
2594 : * @param[out] spec where to free the data
2595 : */
2596 : static void
2597 14 : cleaner_array_of_blinded_denom_sigs (
2598 : void *cls,
2599 : struct GNUNET_JSON_Specification *spec)
2600 : {
2601 14 : struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
2602 14 : size_t num_entries = (size_t) cls;
2603 :
2604 70 : for (size_t i = 0; i < num_entries; i++)
2605 : {
2606 56 : if (NULL != sigs[i].blinded_sig)
2607 : {
2608 56 : TALER_blinded_denom_sig_free (&sigs[i]);
2609 56 : sigs[i].blinded_sig = NULL;
2610 : }
2611 : }
2612 14 : }
2613 :
2614 :
2615 : struct GNUNET_JSON_Specification
2616 14 : TALER_JSON_spec_array_of_blinded_denom_sigs (
2617 : const char *field,
2618 : size_t num_entries,
2619 : struct TALER_BlindedDenominationSignature *entries)
2620 : {
2621 14 : struct GNUNET_JSON_Specification ret = {
2622 : .parser = &parse_array_of_blinded_denom_sigs,
2623 : .ptr = entries,
2624 : .field = field,
2625 : .cleaner = &cleaner_array_of_blinded_denom_sigs,
2626 14 : .cls = (void *) num_entries,
2627 : };
2628 :
2629 70 : for (size_t i = 0; i<num_entries; i++)
2630 56 : entries[i].blinded_sig = NULL;
2631 14 : return ret;
2632 : }
2633 :
2634 :
2635 : /* end of json/json_helper.c */
|