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 1209 : string_to_cipher (const char *cipher_s)
36 : {
37 1209 : if ((0 == strcasecmp (cipher_s,
38 642 : "RSA")) ||
39 642 : (0 == strcasecmp (cipher_s,
40 : "RSA+age_restricted")))
41 652 : return GNUNET_CRYPTO_BSA_RSA;
42 557 : if ((0 == strcasecmp (cipher_s,
43 80 : "CS")) ||
44 80 : (0 == strcasecmp (cipher_s,
45 : "CS+age_restricted")))
46 557 : return GNUNET_CRYPTO_BSA_CS;
47 0 : return GNUNET_CRYPTO_BSA_INVALID;
48 : }
49 :
50 :
51 : json_t *
52 10982 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
53 : {
54 10982 : char *amount_str = TALER_amount_to_string (amount);
55 :
56 10982 : GNUNET_assert (NULL != amount_str);
57 : {
58 10982 : json_t *j = json_string (amount_str);
59 :
60 10982 : GNUNET_free (amount_str);
61 10982 : 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 8357 : parse_amount (void *cls,
76 : json_t *root,
77 : struct GNUNET_JSON_Specification *spec)
78 : {
79 8357 : const char *currency = cls;
80 8357 : struct TALER_Amount *r_amount = spec->ptr;
81 :
82 : (void) cls;
83 8357 : if (! json_is_string (root))
84 : {
85 0 : GNUNET_break_op (0);
86 0 : return GNUNET_SYSERR;
87 : }
88 8357 : if (GNUNET_OK !=
89 8357 : 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 8357 : if ( (NULL != currency) &&
96 : (0 !=
97 5749 : strcasecmp (currency,
98 5749 : 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 8357 : return GNUNET_OK;
109 : }
110 :
111 :
112 : struct GNUNET_JSON_Specification
113 5780 : TALER_JSON_spec_amount (const char *name,
114 : const char *currency,
115 : struct TALER_Amount *r_amount)
116 : {
117 5780 : 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 5780 : GNUNET_assert (NULL != currency);
128 5780 : return ret;
129 : }
130 :
131 :
132 : struct GNUNET_JSON_Specification
133 2793 : TALER_JSON_spec_amount_any (const char *name,
134 : struct TALER_Amount *r_amount)
135 : {
136 2793 : 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 2793 : 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 50 : parse_cspec (void *cls,
377 : json_t *root,
378 : struct GNUNET_JSON_Specification *spec)
379 : {
380 50 : struct TALER_CurrencySpecification *r_cspec = spec->ptr;
381 50 : 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 50 : const json_t *ca = NULL;
388 : struct GNUNET_JSON_Specification gspec[] = {
389 50 : GNUNET_JSON_spec_string ("name",
390 : &name),
391 50 : GNUNET_JSON_spec_uint32 ("num_fractional_input_digits",
392 : &fid),
393 50 : GNUNET_JSON_spec_uint32 ("num_fractional_normal_digits",
394 : &fnd),
395 50 : GNUNET_JSON_spec_uint32 ("num_fractional_trailing_zero_digits",
396 : &ftzd),
397 50 : GNUNET_JSON_spec_object_const ("alt_unit_names",
398 : &map),
399 50 : GNUNET_JSON_spec_mark_optional (
400 : GNUNET_JSON_spec_array_const ("common_amounts",
401 : &ca),
402 : NULL),
403 50 : GNUNET_JSON_spec_end ()
404 : };
405 : const char *emsg;
406 : unsigned int eline;
407 :
408 50 : memset (r_cspec->currency,
409 : 0,
410 : sizeof (r_cspec->currency));
411 50 : if (GNUNET_OK !=
412 50 : 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 50 : if (strlen (currency) >= TALER_CURRENCY_LEN)
426 : {
427 0 : GNUNET_break_op (0);
428 0 : return GNUNET_SYSERR;
429 : }
430 50 : if ( (fid > TALER_AMOUNT_FRAC_LEN) ||
431 50 : (fnd > TALER_AMOUNT_FRAC_LEN) ||
432 50 : (ftzd > TALER_AMOUNT_FRAC_LEN) )
433 : {
434 0 : GNUNET_break_op (0);
435 0 : return GNUNET_SYSERR;
436 : }
437 50 : if (GNUNET_OK !=
438 50 : TALER_check_currency (currency))
439 : {
440 0 : GNUNET_break_op (0);
441 0 : return GNUNET_SYSERR;
442 : }
443 50 : strcpy (r_cspec->currency,
444 : currency);
445 50 : if (GNUNET_OK !=
446 50 : TALER_check_currency_scale_map (map))
447 : {
448 0 : GNUNET_break_op (0);
449 0 : return GNUNET_SYSERR;
450 : }
451 50 : r_cspec->name = GNUNET_strdup (name);
452 50 : r_cspec->map_alt_unit_names = json_incref ((json_t *) map);
453 50 : if (NULL != ca)
454 : {
455 : size_t i;
456 : json_t *v;
457 :
458 250 : json_array_foreach ((json_t *) ca, i, v)
459 : {
460 : struct TALER_Amount val;
461 : const char *vstr;
462 :
463 200 : vstr = json_string_value (v);
464 400 : if ( (NULL == vstr) ||
465 : (GNUNET_OK !=
466 200 : TALER_string_to_amount (vstr,
467 : &val)) )
468 : {
469 0 : GNUNET_break_op (0);
470 0 : return GNUNET_SYSERR;
471 : }
472 200 : if (0 != strcasecmp (val.currency,
473 200 : r_cspec->currency))
474 : {
475 0 : GNUNET_break_op (0);
476 0 : return GNUNET_SYSERR;
477 : }
478 200 : GNUNET_array_append (r_cspec->common_amounts,
479 : r_cspec->num_common_amounts,
480 : val);
481 : }
482 : }
483 50 : 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 50 : TALER_JSON_spec_currency_specification (
510 : const char *name,
511 : const char *currency,
512 : struct TALER_CurrencySpecification *r_cspec)
513 : {
514 50 : 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 50 : memset (r_cspec,
525 : 0,
526 : sizeof (*r_cspec));
527 50 : return ret;
528 : }
529 :
530 :
531 : static enum GNUNET_GenericReturnValue
532 353 : parse_denomination_group (void *cls,
533 : json_t *root,
534 : struct GNUNET_JSON_Specification *spec)
535 : {
536 353 : struct TALER_DenominationGroup *group = spec->ptr;
537 : const char *cipher;
538 353 : const char *currency = cls;
539 353 : bool age_mask_missing = false;
540 353 : bool has_age_restricted_suffix = false;
541 : struct GNUNET_JSON_Specification gspec[] = {
542 353 : GNUNET_JSON_spec_string ("cipher",
543 : &cipher),
544 353 : TALER_JSON_spec_amount ("value",
545 : currency,
546 : &group->value),
547 353 : TALER_JSON_SPEC_DENOM_FEES ("fee",
548 : currency,
549 : &group->fees),
550 353 : GNUNET_JSON_spec_mark_optional (
551 : GNUNET_JSON_spec_uint32 ("age_mask",
552 : &group->age_mask.bits),
553 : &age_mask_missing),
554 353 : GNUNET_JSON_spec_end ()
555 : };
556 : const char *emsg;
557 : unsigned int eline;
558 :
559 353 : if (GNUNET_OK !=
560 353 : 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 353 : group->cipher = string_to_cipher (cipher);
575 353 : 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 353 : has_age_restricted_suffix =
583 353 : (NULL != strstr (cipher, "+age_restricted"));
584 353 : if (has_age_restricted_suffix && age_mask_missing)
585 : {
586 0 : GNUNET_break_op (0);
587 0 : return GNUNET_SYSERR;
588 : }
589 :
590 353 : if (age_mask_missing)
591 188 : group->age_mask.bits = 0;
592 :
593 353 : return GNUNET_OK;
594 : }
595 :
596 :
597 : struct GNUNET_JSON_Specification
598 353 : TALER_JSON_spec_denomination_group (const char *name,
599 : const char *currency,
600 : struct TALER_DenominationGroup *group)
601 : {
602 353 : 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 353 : 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 29 : parse_econtract (void *cls,
624 : json_t *root,
625 : struct GNUNET_JSON_Specification *spec)
626 : {
627 29 : struct TALER_EncryptedContract *econtract = spec->ptr;
628 : struct GNUNET_JSON_Specification ispec[] = {
629 29 : GNUNET_JSON_spec_varsize ("econtract",
630 : &econtract->econtract,
631 : &econtract->econtract_size),
632 29 : GNUNET_JSON_spec_fixed_auto ("econtract_sig",
633 : &econtract->econtract_sig),
634 29 : GNUNET_JSON_spec_fixed_auto ("contract_pub",
635 : &econtract->contract_pub),
636 29 : GNUNET_JSON_spec_end ()
637 : };
638 : const char *emsg;
639 : unsigned int eline;
640 :
641 : (void) cls;
642 29 : if (GNUNET_OK !=
643 29 : GNUNET_JSON_parse (root,
644 : ispec,
645 : &emsg,
646 : &eline))
647 : {
648 0 : GNUNET_break_op (0);
649 0 : return GNUNET_SYSERR;
650 : }
651 29 : 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 13 : clean_econtract (void *cls,
663 : struct GNUNET_JSON_Specification *spec)
664 : {
665 13 : struct TALER_EncryptedContract *econtract = spec->ptr;
666 :
667 : (void) cls;
668 13 : GNUNET_free (econtract->econtract);
669 13 : }
670 :
671 :
672 : struct GNUNET_JSON_Specification
673 29 : TALER_JSON_spec_econtract (const char *name,
674 : struct TALER_EncryptedContract *econtract)
675 : {
676 29 : struct GNUNET_JSON_Specification ret = {
677 : .parser = &parse_econtract,
678 : .cleaner = &clean_econtract,
679 : .field = name,
680 : .ptr = econtract
681 : };
682 :
683 29 : 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 22 : clean_age_commitment (void *cls,
760 : struct GNUNET_JSON_Specification *spec)
761 : {
762 22 : struct TALER_AgeCommitment *age_commitment = spec->ptr;
763 :
764 : (void) cls;
765 22 : if ( (NULL == age_commitment) ||
766 22 : (NULL == age_commitment->pubs) )
767 14 : return;
768 8 : age_commitment->num = 0;
769 8 : GNUNET_free (age_commitment->pubs);
770 : }
771 :
772 :
773 : struct GNUNET_JSON_Specification
774 42 : TALER_JSON_spec_age_commitment (const char *name,
775 : struct TALER_AgeCommitment *age_commitment)
776 : {
777 42 : 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 42 : 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 856 : parse_denom_pub (void *cls,
829 : json_t *root,
830 : struct GNUNET_JSON_Specification *spec)
831 : {
832 856 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
833 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
834 : const char *cipher;
835 856 : bool age_mask_missing = false;
836 : struct GNUNET_JSON_Specification dspec[] = {
837 856 : GNUNET_JSON_spec_string ("cipher",
838 : &cipher),
839 856 : GNUNET_JSON_spec_mark_optional (
840 : GNUNET_JSON_spec_uint32 ("age_mask",
841 : &denom_pub->age_mask.bits),
842 : &age_mask_missing),
843 856 : GNUNET_JSON_spec_end ()
844 : };
845 : const char *emsg;
846 : unsigned int eline;
847 :
848 : (void) cls;
849 856 : if (GNUNET_OK !=
850 856 : 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 856 : if (age_mask_missing)
860 0 : denom_pub->age_mask.bits = 0;
861 856 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
862 856 : bsign_pub->rc = 1;
863 856 : bsign_pub->cipher = string_to_cipher (cipher);
864 856 : switch (bsign_pub->cipher)
865 : {
866 0 : case GNUNET_CRYPTO_BSA_INVALID:
867 0 : break;
868 470 : case GNUNET_CRYPTO_BSA_RSA:
869 : {
870 : struct GNUNET_JSON_Specification ispec[] = {
871 470 : GNUNET_JSON_spec_rsa_public_key (
872 : "rsa_pub",
873 : &bsign_pub->details.rsa_public_key),
874 470 : GNUNET_JSON_spec_end ()
875 : };
876 :
877 470 : if (GNUNET_OK !=
878 470 : 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 470 : GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key,
888 : &bsign_pub->pub_key_hash);
889 470 : denom_pub->bsign_pub_key = bsign_pub;
890 470 : return GNUNET_OK;
891 : }
892 386 : case GNUNET_CRYPTO_BSA_CS:
893 : {
894 : struct GNUNET_JSON_Specification ispec[] = {
895 386 : GNUNET_JSON_spec_fixed ("cs_pub",
896 386 : &bsign_pub->details.cs_public_key,
897 : sizeof (bsign_pub->details.cs_public_key)),
898 386 : GNUNET_JSON_spec_end ()
899 : };
900 :
901 386 : if (GNUNET_OK !=
902 386 : GNUNET_JSON_parse (root,
903 : ispec,
904 : &emsg,
905 : &eline))
906 : {
907 0 : GNUNET_break_op (0);
908 0 : GNUNET_free (bsign_pub);
909 0 : return GNUNET_SYSERR;
910 : }
911 386 : GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
912 : sizeof(bsign_pub->details.cs_public_key),
913 : &bsign_pub->pub_key_hash);
914 386 : denom_pub->bsign_pub_key = bsign_pub;
915 386 : return GNUNET_OK;
916 : }
917 : }
918 0 : GNUNET_break_op (0);
919 0 : GNUNET_free (bsign_pub);
920 0 : return GNUNET_SYSERR;
921 : }
922 :
923 :
924 : /**
925 : * Cleanup data left from parsing denomination public key.
926 : *
927 : * @param cls closure, NULL
928 : * @param[out] spec where to free the data
929 : */
930 : static void
931 603 : clean_denom_pub (void *cls,
932 : struct GNUNET_JSON_Specification *spec)
933 : {
934 603 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
935 :
936 : (void) cls;
937 603 : TALER_denom_pub_free (denom_pub);
938 603 : }
939 :
940 :
941 : struct GNUNET_JSON_Specification
942 856 : TALER_JSON_spec_denom_pub (const char *field,
943 : struct TALER_DenominationPublicKey *pk)
944 : {
945 856 : struct GNUNET_JSON_Specification ret = {
946 : .parser = &parse_denom_pub,
947 : .cleaner = &clean_denom_pub,
948 : .field = field,
949 : .ptr = pk
950 : };
951 :
952 856 : pk->bsign_pub_key = NULL;
953 856 : return ret;
954 : }
955 :
956 :
957 : /**
958 : * Parse given JSON object to token issue public key.
959 : *
960 : * @param cls closure, NULL
961 : * @param root the json object representing data
962 : * @param[out] spec where to write the data
963 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
964 : */
965 : static enum GNUNET_GenericReturnValue
966 0 : parse_token_pub (void *cls,
967 : json_t *root,
968 : struct GNUNET_JSON_Specification *spec)
969 : {
970 0 : struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
971 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
972 : const char *cipher;
973 : struct GNUNET_JSON_Specification dspec[] = {
974 0 : GNUNET_JSON_spec_string ("cipher",
975 : &cipher),
976 0 : GNUNET_JSON_spec_end ()
977 : };
978 : const char *emsg;
979 : unsigned int eline;
980 :
981 : (void) cls;
982 0 : if (GNUNET_OK !=
983 0 : GNUNET_JSON_parse (root,
984 : dspec,
985 : &emsg,
986 : &eline))
987 : {
988 0 : GNUNET_break_op (0);
989 0 : return GNUNET_SYSERR;
990 : }
991 :
992 0 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
993 0 : bsign_pub->rc = 1;
994 0 : bsign_pub->cipher = string_to_cipher (cipher);
995 0 : switch (bsign_pub->cipher)
996 : {
997 0 : case GNUNET_CRYPTO_BSA_INVALID:
998 0 : break;
999 0 : case GNUNET_CRYPTO_BSA_RSA:
1000 : {
1001 : struct GNUNET_JSON_Specification ispec[] = {
1002 0 : GNUNET_JSON_spec_rsa_public_key (
1003 : "rsa_pub",
1004 : &bsign_pub->details.rsa_public_key),
1005 0 : GNUNET_JSON_spec_end ()
1006 : };
1007 :
1008 0 : if (GNUNET_OK !=
1009 0 : GNUNET_JSON_parse (root,
1010 : ispec,
1011 : &emsg,
1012 : &eline))
1013 : {
1014 0 : GNUNET_break_op (0);
1015 0 : GNUNET_free (bsign_pub);
1016 0 : return GNUNET_SYSERR;
1017 : }
1018 0 : GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key,
1019 : &bsign_pub->pub_key_hash);
1020 0 : token_pub->public_key = bsign_pub;
1021 0 : return GNUNET_OK;
1022 : }
1023 0 : case GNUNET_CRYPTO_BSA_CS:
1024 : {
1025 : struct GNUNET_JSON_Specification ispec[] = {
1026 0 : GNUNET_JSON_spec_fixed ("cs_pub",
1027 0 : &bsign_pub->details.cs_public_key,
1028 : sizeof (bsign_pub->details.cs_public_key)),
1029 0 : GNUNET_JSON_spec_end ()
1030 : };
1031 :
1032 0 : if (GNUNET_OK !=
1033 0 : GNUNET_JSON_parse (root,
1034 : ispec,
1035 : &emsg,
1036 : &eline))
1037 : {
1038 0 : GNUNET_break_op (0);
1039 0 : GNUNET_free (bsign_pub);
1040 0 : return GNUNET_SYSERR;
1041 : }
1042 0 : GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
1043 : sizeof(bsign_pub->details.cs_public_key),
1044 : &bsign_pub->pub_key_hash);
1045 0 : token_pub->public_key = bsign_pub;
1046 0 : return GNUNET_OK;
1047 : }
1048 : }
1049 0 : GNUNET_break_op (0);
1050 0 : GNUNET_free (bsign_pub);
1051 0 : return GNUNET_SYSERR;
1052 : }
1053 :
1054 :
1055 : /**
1056 : * Cleanup data left from parsing token issue public key.
1057 : *
1058 : * @param cls closure, NULL
1059 : * @param[out] spec where to free the data
1060 : */
1061 : static void
1062 0 : clean_token_pub (void *cls,
1063 : struct GNUNET_JSON_Specification *spec)
1064 : {
1065 0 : struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
1066 :
1067 : (void) cls;
1068 0 : TALER_token_issue_pub_free (token_pub);
1069 0 : }
1070 :
1071 :
1072 : struct GNUNET_JSON_Specification
1073 0 : TALER_JSON_spec_token_pub (const char *field,
1074 : struct TALER_TokenIssuePublicKey *pk)
1075 : {
1076 0 : struct GNUNET_JSON_Specification ret = {
1077 : .field = field,
1078 : .parser = &parse_token_pub,
1079 : .cleaner = &clean_token_pub,
1080 : .ptr = pk
1081 : };
1082 :
1083 0 : pk->public_key = NULL;
1084 0 : return ret;
1085 : }
1086 :
1087 :
1088 : /**
1089 : * Parse given JSON object partially into a denomination public key.
1090 : *
1091 : * Depending on the cipher in cls, it parses the corresponding public key type.
1092 : *
1093 : * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm
1094 : * @param root the json object representing data
1095 : * @param[out] spec where to write the data
1096 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1097 : */
1098 : static enum GNUNET_GenericReturnValue
1099 1021 : parse_denom_pub_cipher (void *cls,
1100 : json_t *root,
1101 : struct GNUNET_JSON_Specification *spec)
1102 : {
1103 1021 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
1104 1021 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher =
1105 1021 : (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls;
1106 : struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
1107 : const char *emsg;
1108 : unsigned int eline;
1109 :
1110 1021 : bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
1111 1021 : bsign_pub->cipher = cipher;
1112 1021 : bsign_pub->rc = 1;
1113 1021 : switch (cipher)
1114 : {
1115 0 : case GNUNET_CRYPTO_BSA_INVALID:
1116 0 : break;
1117 527 : case GNUNET_CRYPTO_BSA_RSA:
1118 : {
1119 : struct GNUNET_JSON_Specification ispec[] = {
1120 527 : GNUNET_JSON_spec_rsa_public_key (
1121 : "rsa_pub",
1122 : &bsign_pub->details.rsa_public_key),
1123 527 : GNUNET_JSON_spec_end ()
1124 : };
1125 :
1126 527 : if (GNUNET_OK !=
1127 527 : GNUNET_JSON_parse (root,
1128 : ispec,
1129 : &emsg,
1130 : &eline))
1131 : {
1132 0 : GNUNET_break_op (0);
1133 0 : GNUNET_free (bsign_pub);
1134 0 : return GNUNET_SYSERR;
1135 : }
1136 527 : GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key,
1137 : &bsign_pub->pub_key_hash);
1138 527 : denom_pub->bsign_pub_key = bsign_pub;
1139 527 : return GNUNET_OK;
1140 : }
1141 494 : case GNUNET_CRYPTO_BSA_CS:
1142 : {
1143 : struct GNUNET_JSON_Specification ispec[] = {
1144 494 : GNUNET_JSON_spec_fixed ("cs_pub",
1145 494 : &bsign_pub->details.cs_public_key,
1146 : sizeof (bsign_pub->details.cs_public_key)),
1147 494 : GNUNET_JSON_spec_end ()
1148 : };
1149 :
1150 494 : if (GNUNET_OK !=
1151 494 : GNUNET_JSON_parse (root,
1152 : ispec,
1153 : &emsg,
1154 : &eline))
1155 : {
1156 0 : GNUNET_break_op (0);
1157 0 : GNUNET_free (bsign_pub);
1158 0 : return GNUNET_SYSERR;
1159 : }
1160 494 : GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
1161 : sizeof(bsign_pub->details.cs_public_key),
1162 : &bsign_pub->pub_key_hash);
1163 494 : denom_pub->bsign_pub_key = bsign_pub;
1164 494 : return GNUNET_OK;
1165 : }
1166 : }
1167 0 : GNUNET_break_op (0);
1168 0 : GNUNET_free (bsign_pub);
1169 0 : return GNUNET_SYSERR;
1170 : }
1171 :
1172 :
1173 : struct GNUNET_JSON_Specification
1174 1021 : TALER_JSON_spec_denom_pub_cipher (
1175 : const char *field,
1176 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
1177 : struct TALER_DenominationPublicKey *pk)
1178 : {
1179 1021 : struct GNUNET_JSON_Specification ret = {
1180 : .parser = &parse_denom_pub_cipher,
1181 : .cleaner = &clean_denom_pub,
1182 : .field = field,
1183 1021 : .cls = (void *) cipher,
1184 : .ptr = pk
1185 : };
1186 :
1187 1021 : pk->bsign_pub_key = NULL;
1188 1021 : return ret;
1189 : }
1190 :
1191 :
1192 : struct GNUNET_JSON_Specification
1193 264 : TALER_JSON_spec_denom_sig (const char *field,
1194 : struct TALER_DenominationSignature *sig)
1195 : {
1196 264 : sig->unblinded_sig = NULL;
1197 264 : return GNUNET_JSON_spec_unblinded_signature (field,
1198 : &sig->unblinded_sig);
1199 : }
1200 :
1201 :
1202 : struct GNUNET_JSON_Specification
1203 170 : TALER_JSON_spec_blinded_denom_sig (
1204 : const char *field,
1205 : struct TALER_BlindedDenominationSignature *sig)
1206 : {
1207 170 : sig->blinded_sig = NULL;
1208 170 : return GNUNET_JSON_spec_blinded_signature (field,
1209 : &sig->blinded_sig);
1210 : }
1211 :
1212 :
1213 : struct GNUNET_JSON_Specification
1214 590 : TALER_JSON_spec_blinded_planchet (
1215 : const char *field,
1216 : struct TALER_BlindedPlanchet *blinded_planchet)
1217 : {
1218 590 : blinded_planchet->blinded_message = NULL;
1219 590 : return GNUNET_JSON_spec_blinded_message (field,
1220 : &blinded_planchet->blinded_message);
1221 : }
1222 :
1223 :
1224 : /**
1225 : * Parse given JSON object to exchange withdraw values (/csr).
1226 : *
1227 : * @param cls closure, NULL
1228 : * @param root the json object representing data
1229 : * @param[out] spec where to write the data
1230 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1231 : */
1232 : static enum GNUNET_GenericReturnValue
1233 0 : parse_exchange_blinding_values (void *cls,
1234 : json_t *root,
1235 : struct GNUNET_JSON_Specification *spec)
1236 : {
1237 0 : struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
1238 : struct GNUNET_CRYPTO_BlindingInputValues *bi;
1239 : const char *cipher;
1240 : struct GNUNET_JSON_Specification dspec[] = {
1241 0 : GNUNET_JSON_spec_string ("cipher",
1242 : &cipher),
1243 0 : GNUNET_JSON_spec_end ()
1244 : };
1245 : const char *emsg;
1246 : unsigned int eline;
1247 : enum GNUNET_CRYPTO_BlindSignatureAlgorithm ci;
1248 :
1249 : (void) cls;
1250 0 : if (GNUNET_OK !=
1251 0 : GNUNET_JSON_parse (root,
1252 : dspec,
1253 : &emsg,
1254 : &eline))
1255 : {
1256 0 : GNUNET_break_op (0);
1257 0 : return GNUNET_SYSERR;
1258 : }
1259 0 : ci = string_to_cipher (cipher);
1260 0 : switch (ci)
1261 : {
1262 0 : case GNUNET_CRYPTO_BSA_INVALID:
1263 0 : break;
1264 0 : case GNUNET_CRYPTO_BSA_RSA:
1265 0 : ewv->blinding_inputs = TALER_denom_ewv_rsa_singleton ()->blinding_inputs;
1266 0 : return GNUNET_OK;
1267 0 : case GNUNET_CRYPTO_BSA_CS:
1268 0 : bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
1269 0 : bi->cipher = GNUNET_CRYPTO_BSA_CS;
1270 0 : bi->rc = 1;
1271 : {
1272 : struct GNUNET_JSON_Specification ispec[] = {
1273 0 : GNUNET_JSON_spec_fixed (
1274 : "r_pub_0",
1275 0 : &bi->details.cs_values.r_pub[0],
1276 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1277 0 : GNUNET_JSON_spec_fixed (
1278 : "r_pub_1",
1279 0 : &bi->details.cs_values.r_pub[1],
1280 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1281 0 : GNUNET_JSON_spec_end ()
1282 : };
1283 :
1284 0 : if (GNUNET_OK !=
1285 0 : GNUNET_JSON_parse (root,
1286 : ispec,
1287 : &emsg,
1288 : &eline))
1289 : {
1290 0 : GNUNET_break_op (0);
1291 0 : GNUNET_free (bi);
1292 0 : return GNUNET_SYSERR;
1293 : }
1294 0 : ewv->blinding_inputs = bi;
1295 0 : return GNUNET_OK;
1296 : }
1297 : }
1298 0 : GNUNET_break_op (0);
1299 0 : return GNUNET_SYSERR;
1300 : }
1301 :
1302 :
1303 : /**
1304 : * Cleanup data left from parsing withdraw values
1305 : *
1306 : * @param cls closure, NULL
1307 : * @param[out] spec where to free the data
1308 : */
1309 : static void
1310 0 : clean_exchange_blinding_values (
1311 : void *cls,
1312 : struct GNUNET_JSON_Specification *spec)
1313 : {
1314 0 : struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
1315 :
1316 : (void) cls;
1317 0 : TALER_denom_ewv_free (ewv);
1318 0 : }
1319 :
1320 :
1321 : struct GNUNET_JSON_Specification
1322 0 : TALER_JSON_spec_exchange_blinding_values (
1323 : const char *field,
1324 : struct TALER_ExchangeBlindingValues *ewv)
1325 : {
1326 0 : struct GNUNET_JSON_Specification ret = {
1327 : .parser = &parse_exchange_blinding_values,
1328 : .cleaner = &clean_exchange_blinding_values,
1329 : .field = field,
1330 : .ptr = ewv
1331 : };
1332 :
1333 0 : ewv->blinding_inputs = NULL;
1334 0 : return ret;
1335 : }
1336 :
1337 :
1338 : /**
1339 : * Closure for #parse_i18n_string.
1340 : */
1341 : struct I18nContext
1342 : {
1343 : /**
1344 : * Language pattern to match.
1345 : */
1346 : char *lp;
1347 :
1348 : /**
1349 : * Name of the field to match.
1350 : */
1351 : const char *field;
1352 : };
1353 :
1354 :
1355 : /**
1356 : * Parse given JSON object to internationalized string.
1357 : *
1358 : * @param cls closure, our `struct I18nContext *`
1359 : * @param root the json object representing data
1360 : * @param[out] spec where to write the data
1361 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1362 : */
1363 : static enum GNUNET_GenericReturnValue
1364 0 : parse_i18n_string (void *cls,
1365 : json_t *root,
1366 : struct GNUNET_JSON_Specification *spec)
1367 : {
1368 0 : struct I18nContext *ctx = cls;
1369 : json_t *i18n;
1370 : json_t *val;
1371 :
1372 : {
1373 : char *i18nf;
1374 :
1375 0 : GNUNET_asprintf (&i18nf,
1376 : "%s_i18n",
1377 : ctx->field);
1378 0 : i18n = json_object_get (root,
1379 : i18nf);
1380 0 : GNUNET_free (i18nf);
1381 : }
1382 :
1383 0 : val = json_object_get (root,
1384 : ctx->field);
1385 0 : if ( (NULL != i18n) &&
1386 0 : (NULL != ctx->lp) )
1387 : {
1388 0 : double best = 0.0;
1389 : json_t *pos;
1390 : const char *lang;
1391 :
1392 0 : json_object_foreach (i18n, lang, pos)
1393 : {
1394 : double score;
1395 :
1396 0 : score = TALER_pattern_matches (ctx->lp,
1397 : lang);
1398 0 : if (score > best)
1399 : {
1400 0 : best = score;
1401 0 : val = pos;
1402 : }
1403 : }
1404 : }
1405 :
1406 : {
1407 : const char *str;
1408 :
1409 0 : str = json_string_value (val);
1410 0 : *(const char **) spec->ptr = str;
1411 : }
1412 0 : return GNUNET_OK;
1413 : }
1414 :
1415 :
1416 : /**
1417 : * Function called to clean up data from earlier parsing.
1418 : *
1419 : * @param cls closure
1420 : * @param spec our specification entry with data to clean.
1421 : */
1422 : static void
1423 0 : i18n_cleaner (void *cls,
1424 : struct GNUNET_JSON_Specification *spec)
1425 : {
1426 0 : struct I18nContext *ctx = cls;
1427 :
1428 : (void) spec;
1429 0 : if (NULL != ctx)
1430 : {
1431 0 : GNUNET_free (ctx->lp);
1432 0 : GNUNET_free (ctx);
1433 : }
1434 0 : }
1435 :
1436 :
1437 : struct GNUNET_JSON_Specification
1438 0 : TALER_JSON_spec_i18n_string (const char *name,
1439 : const char *language_pattern,
1440 : const char **strptr)
1441 : {
1442 0 : struct I18nContext *ctx = GNUNET_new (struct I18nContext);
1443 0 : struct GNUNET_JSON_Specification ret = {
1444 : .parser = &parse_i18n_string,
1445 : .cleaner = &i18n_cleaner,
1446 : .cls = ctx,
1447 : .field = NULL, /* we want the main object */
1448 : .ptr = strptr,
1449 : .ptr_size = 0,
1450 : .size_ptr = NULL
1451 : };
1452 :
1453 0 : ctx->lp = (NULL != language_pattern)
1454 0 : ? GNUNET_strdup (language_pattern)
1455 0 : : NULL;
1456 0 : ctx->field = name;
1457 0 : *strptr = NULL;
1458 0 : return ret;
1459 : }
1460 :
1461 :
1462 : struct GNUNET_JSON_Specification
1463 0 : TALER_JSON_spec_i18n_str (const char *name,
1464 : const char **strptr)
1465 : {
1466 0 : const char *lang = getenv ("LANG");
1467 : const char *dot;
1468 : char *l;
1469 : struct GNUNET_JSON_Specification ret;
1470 :
1471 0 : if (NULL != lang)
1472 : {
1473 0 : dot = strchr (lang,
1474 : '.');
1475 0 : if (NULL == dot)
1476 0 : l = GNUNET_strdup (lang);
1477 : else
1478 0 : l = GNUNET_strndup (lang,
1479 : dot - lang);
1480 : }
1481 : else
1482 : {
1483 0 : l = NULL;
1484 : }
1485 0 : ret = TALER_JSON_spec_i18n_string (name,
1486 : l,
1487 : strptr);
1488 0 : GNUNET_free (l);
1489 0 : return ret;
1490 : }
1491 :
1492 :
1493 : /**
1494 : * Parse given JSON object with Taler error code.
1495 : *
1496 : * @param cls closure, NULL
1497 : * @param root the json object representing data
1498 : * @param[out] spec where to write the data
1499 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1500 : */
1501 : static enum GNUNET_GenericReturnValue
1502 0 : parse_ec (void *cls,
1503 : json_t *root,
1504 : struct GNUNET_JSON_Specification *spec)
1505 : {
1506 0 : enum TALER_ErrorCode *ec = spec->ptr;
1507 : json_int_t num;
1508 :
1509 : (void) cls;
1510 0 : if (! json_is_integer (root))
1511 : {
1512 0 : GNUNET_break_op (0);
1513 0 : return GNUNET_SYSERR;
1514 : }
1515 0 : num = json_integer_value (root);
1516 0 : if (num < 0)
1517 : {
1518 0 : GNUNET_break_op (0);
1519 0 : *ec = TALER_EC_INVALID;
1520 0 : return GNUNET_SYSERR;
1521 : }
1522 0 : *ec = (enum TALER_ErrorCode) num;
1523 0 : return GNUNET_OK;
1524 : }
1525 :
1526 :
1527 : struct GNUNET_JSON_Specification
1528 0 : TALER_JSON_spec_ec (const char *field,
1529 : enum TALER_ErrorCode *ec)
1530 : {
1531 0 : struct GNUNET_JSON_Specification ret = {
1532 : .parser = &parse_ec,
1533 : .field = field,
1534 : .ptr = ec
1535 : };
1536 :
1537 0 : *ec = TALER_EC_NONE;
1538 0 : return ret;
1539 : }
1540 :
1541 :
1542 : /**
1543 : * Parse given JSON object to web URL.
1544 : *
1545 : * @param cls closure, NULL
1546 : * @param root the json object representing data
1547 : * @param[out] spec where to write the data
1548 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1549 : */
1550 : static enum GNUNET_GenericReturnValue
1551 139 : parse_web_url (void *cls,
1552 : json_t *root,
1553 : struct GNUNET_JSON_Specification *spec)
1554 : {
1555 : const char *str;
1556 :
1557 : (void) cls;
1558 139 : str = json_string_value (root);
1559 139 : if (NULL == str)
1560 : {
1561 0 : GNUNET_break_op (0);
1562 0 : return GNUNET_SYSERR;
1563 : }
1564 139 : if (! TALER_is_web_url (str))
1565 : {
1566 0 : GNUNET_break_op (0);
1567 0 : return GNUNET_SYSERR;
1568 : }
1569 139 : *(const char **) spec->ptr = str;
1570 139 : return GNUNET_OK;
1571 : }
1572 :
1573 :
1574 : struct GNUNET_JSON_Specification
1575 585 : TALER_JSON_spec_web_url (const char *field,
1576 : const char **url)
1577 : {
1578 585 : struct GNUNET_JSON_Specification ret = {
1579 : .parser = &parse_web_url,
1580 : .field = field,
1581 : .ptr = url
1582 : };
1583 :
1584 585 : *url = NULL;
1585 585 : return ret;
1586 : }
1587 :
1588 :
1589 : /**
1590 : * Parse given JSON object to web URL, and make a copy.
1591 : *
1592 : * @param cls closure, NULL
1593 : * @param root the json object representing data
1594 : * @param[out] spec where to write the data
1595 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1596 : */
1597 : static enum GNUNET_GenericReturnValue
1598 0 : parse_web_url_copy (void *cls,
1599 : json_t *root,
1600 : struct GNUNET_JSON_Specification *spec)
1601 : {
1602 : const char *str;
1603 :
1604 : (void) cls;
1605 0 : str = json_string_value (root);
1606 0 : if (NULL == str)
1607 : {
1608 0 : GNUNET_break_op (0);
1609 0 : return GNUNET_SYSERR;
1610 : }
1611 0 : if (! TALER_is_web_url (str))
1612 : {
1613 0 : GNUNET_break_op (0);
1614 0 : return GNUNET_SYSERR;
1615 : }
1616 0 : *(char **) spec->ptr = GNUNET_strdup (str);
1617 0 : return GNUNET_OK;
1618 : }
1619 :
1620 :
1621 : struct GNUNET_JSON_Specification
1622 0 : TALER_JSON_spec_web_url_copy (const char *field,
1623 : char **url)
1624 : {
1625 0 : struct GNUNET_JSON_Specification ret = {
1626 : .parser = &parse_web_url_copy,
1627 : .field = field,
1628 : .ptr = url
1629 : };
1630 :
1631 0 : *url = NULL;
1632 0 : return ret;
1633 : }
1634 :
1635 :
1636 : /**
1637 : * Parse given JSON object to slug.
1638 : *
1639 : * @param cls closure, NULL
1640 : * @param root the json object representing data
1641 : * @param[out] spec where to write the data
1642 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1643 : */
1644 : static enum GNUNET_GenericReturnValue
1645 14 : parse_slug (void *cls,
1646 : json_t *root,
1647 : struct GNUNET_JSON_Specification *spec)
1648 : {
1649 : const char *str;
1650 :
1651 : (void) cls;
1652 14 : str = json_string_value (root);
1653 14 : if (NULL == str)
1654 : {
1655 0 : GNUNET_break_op (0);
1656 0 : return GNUNET_SYSERR;
1657 : }
1658 14 : if (! TALER_is_slug (str))
1659 : {
1660 0 : GNUNET_break_op (0);
1661 0 : return GNUNET_SYSERR;
1662 : }
1663 14 : *(const char **) spec->ptr = str;
1664 14 : return GNUNET_OK;
1665 : }
1666 :
1667 :
1668 : struct GNUNET_JSON_Specification
1669 14 : TALER_JSON_spec_slug (const char *field,
1670 : const char **slug)
1671 : {
1672 14 : struct GNUNET_JSON_Specification ret = {
1673 : .parser = &parse_slug,
1674 : .field = field,
1675 : .ptr = slug
1676 : };
1677 :
1678 14 : *slug = NULL;
1679 14 : return ret;
1680 : }
1681 :
1682 :
1683 : /**
1684 : * Parse given JSON object to slug.
1685 : *
1686 : * @param cls closure, NULL
1687 : * @param root the json object representing data
1688 : * @param[out] spec where to write the data
1689 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1690 : */
1691 : static enum GNUNET_GenericReturnValue
1692 0 : parse_slug_copy (void *cls,
1693 : json_t *root,
1694 : struct GNUNET_JSON_Specification *spec)
1695 : {
1696 : const char *str;
1697 :
1698 : (void) cls;
1699 0 : str = json_string_value (root);
1700 0 : if (NULL == str)
1701 : {
1702 0 : GNUNET_break_op (0);
1703 0 : return GNUNET_SYSERR;
1704 : }
1705 0 : if (! TALER_is_slug (str))
1706 : {
1707 0 : GNUNET_break_op (0);
1708 0 : return GNUNET_SYSERR;
1709 : }
1710 0 : *(char **) spec->ptr = GNUNET_strdup (str);
1711 0 : return GNUNET_OK;
1712 : }
1713 :
1714 :
1715 : struct GNUNET_JSON_Specification
1716 0 : TALER_JSON_spec_slug_copy (const char *field,
1717 : char **slug)
1718 : {
1719 0 : struct GNUNET_JSON_Specification ret = {
1720 : .parser = &parse_slug_copy,
1721 : .field = field,
1722 : .ptr = slug
1723 : };
1724 :
1725 0 : *slug = NULL;
1726 0 : return ret;
1727 : }
1728 :
1729 :
1730 : /**
1731 : * Parse given JSON object to a session ID.
1732 : *
1733 : * @param cls closure, NULL
1734 : * @param root the json object representing data
1735 : * @param[out] spec where to write the data
1736 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1737 : */
1738 : static enum GNUNET_GenericReturnValue
1739 0 : parse_session_id (void *cls,
1740 : json_t *root,
1741 : struct GNUNET_JSON_Specification *spec)
1742 : {
1743 : const char *str;
1744 :
1745 : (void) cls;
1746 0 : str = json_string_value (root);
1747 0 : if (NULL == str)
1748 : {
1749 0 : GNUNET_break_op (0);
1750 0 : return GNUNET_SYSERR;
1751 : }
1752 0 : if (! TALER_is_session_id (str))
1753 : {
1754 0 : GNUNET_break_op (0);
1755 0 : return GNUNET_SYSERR;
1756 : }
1757 0 : *(const char **) spec->ptr = str;
1758 0 : return GNUNET_OK;
1759 : }
1760 :
1761 :
1762 : struct GNUNET_JSON_Specification
1763 0 : TALER_JSON_spec_session_id (const char *field,
1764 : const char **session_id)
1765 : {
1766 0 : struct GNUNET_JSON_Specification ret = {
1767 : .parser = &parse_session_id,
1768 : .field = field,
1769 : .ptr = session_id
1770 : };
1771 :
1772 0 : *session_id = NULL;
1773 0 : return ret;
1774 : }
1775 :
1776 :
1777 : /**
1778 : * Parse given JSON object to a session ID that must not be empty.
1779 : *
1780 : * @param cls closure, NULL
1781 : * @param root the json object representing data
1782 : * @param[out] spec where to write the data
1783 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1784 : */
1785 : static enum GNUNET_GenericReturnValue
1786 0 : parse_nonempty_session_id (void *cls,
1787 : json_t *root,
1788 : struct GNUNET_JSON_Specification *spec)
1789 : {
1790 0 : if (GNUNET_OK !=
1791 0 : parse_session_id (cls,
1792 : root,
1793 : spec))
1794 0 : return GNUNET_SYSERR;
1795 0 : if ('\0' == (*(const char **) spec->ptr)[0])
1796 : {
1797 0 : GNUNET_break_op (0);
1798 0 : return GNUNET_SYSERR;
1799 : }
1800 0 : return GNUNET_OK;
1801 : }
1802 :
1803 :
1804 : struct GNUNET_JSON_Specification
1805 0 : TALER_JSON_spec_nonempty_session_id (const char *field,
1806 : const char **session_id)
1807 : {
1808 0 : struct GNUNET_JSON_Specification ret = {
1809 : .parser = &parse_nonempty_session_id,
1810 : .field = field,
1811 : .ptr = session_id
1812 : };
1813 :
1814 0 : *session_id = NULL;
1815 0 : return ret;
1816 : }
1817 :
1818 :
1819 : /**
1820 : * Parse given JSON object to payto:// URI.
1821 : *
1822 : * @param cls closure, NULL
1823 : * @param root the json object representing data
1824 : * @param[out] spec where to write the data
1825 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1826 : */
1827 : static enum GNUNET_GenericReturnValue
1828 1008 : parse_full_payto_uri (void *cls,
1829 : json_t *root,
1830 : struct GNUNET_JSON_Specification *spec)
1831 : {
1832 1008 : struct TALER_FullPayto *payto_uri = spec->ptr;
1833 : const char *str;
1834 : char *err;
1835 :
1836 : (void) cls;
1837 1008 : str = json_string_value (root);
1838 1008 : if (NULL == str)
1839 : {
1840 0 : GNUNET_break_op (0);
1841 0 : return GNUNET_SYSERR;
1842 : }
1843 1008 : payto_uri->full_payto = (char *) str;
1844 1008 : err = TALER_payto_validate (*payto_uri);
1845 1008 : if (NULL != err)
1846 : {
1847 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1848 : "payto:// malformed: %s\n",
1849 : err);
1850 0 : GNUNET_free (err);
1851 0 : payto_uri->full_payto = NULL;
1852 0 : return GNUNET_SYSERR;
1853 : }
1854 1008 : return GNUNET_OK;
1855 : }
1856 :
1857 :
1858 : struct GNUNET_JSON_Specification
1859 1010 : TALER_JSON_spec_full_payto_uri (
1860 : const char *field,
1861 : struct TALER_FullPayto *payto_uri)
1862 : {
1863 1010 : struct GNUNET_JSON_Specification ret = {
1864 : .parser = &parse_full_payto_uri,
1865 : .field = field,
1866 : .ptr = payto_uri
1867 : };
1868 :
1869 1010 : payto_uri->full_payto = NULL;
1870 1010 : return ret;
1871 : }
1872 :
1873 :
1874 : /**
1875 : * Parse given JSON object to payto:// URI.
1876 : *
1877 : * @param cls closure, NULL
1878 : * @param root the json object representing data
1879 : * @param[out] spec where to write the data
1880 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1881 : */
1882 : static enum GNUNET_GenericReturnValue
1883 6 : parse_normalized_payto_uri (void *cls,
1884 : json_t *root,
1885 : struct GNUNET_JSON_Specification *spec)
1886 : {
1887 6 : struct TALER_NormalizedPayto *payto_uri = spec->ptr;
1888 : const char *str;
1889 :
1890 : (void) cls;
1891 6 : str = json_string_value (root);
1892 6 : if (NULL == str)
1893 : {
1894 0 : GNUNET_break_op (0);
1895 0 : return GNUNET_SYSERR;
1896 : }
1897 6 : payto_uri->normalized_payto = (char *) str;
1898 : {
1899 : char *err;
1900 :
1901 6 : err = TALER_normalized_payto_validate (*payto_uri);
1902 6 : if (NULL != err)
1903 : {
1904 0 : GNUNET_break_op (0);
1905 0 : GNUNET_free (err);
1906 0 : payto_uri->normalized_payto = NULL;
1907 0 : return GNUNET_SYSERR;
1908 : }
1909 : }
1910 6 : return GNUNET_OK;
1911 : }
1912 :
1913 :
1914 : struct GNUNET_JSON_Specification
1915 6 : TALER_JSON_spec_normalized_payto_uri (
1916 : const char *field,
1917 : struct TALER_NormalizedPayto *payto_uri)
1918 : {
1919 6 : struct GNUNET_JSON_Specification ret = {
1920 : .parser = &parse_normalized_payto_uri,
1921 : .field = field,
1922 : .ptr = payto_uri
1923 : };
1924 :
1925 6 : payto_uri->normalized_payto = NULL;
1926 6 : return ret;
1927 : }
1928 :
1929 :
1930 : /**
1931 : * Parse given JSON object with protocol version.
1932 : *
1933 : * @param cls closure, NULL
1934 : * @param root the json object representing data
1935 : * @param[out] spec where to write the data
1936 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1937 : */
1938 : static enum GNUNET_GenericReturnValue
1939 55 : parse_protocol_version (void *cls,
1940 : json_t *root,
1941 : struct GNUNET_JSON_Specification *spec)
1942 : {
1943 55 : struct TALER_JSON_ProtocolVersion *pv = spec->ptr;
1944 : const char *ver;
1945 : char dummy;
1946 :
1947 : (void) cls;
1948 55 : if (! json_is_string (root))
1949 : {
1950 0 : GNUNET_break_op (0);
1951 0 : return GNUNET_SYSERR;
1952 : }
1953 55 : ver = json_string_value (root);
1954 55 : if (3 != sscanf (ver,
1955 : "%u:%u:%u%c",
1956 : &pv->current,
1957 : &pv->revision,
1958 : &pv->age,
1959 : &dummy))
1960 : {
1961 0 : GNUNET_break_op (0);
1962 0 : return GNUNET_SYSERR;
1963 : }
1964 55 : return GNUNET_OK;
1965 : }
1966 :
1967 :
1968 : struct GNUNET_JSON_Specification
1969 55 : TALER_JSON_spec_version (const char *field,
1970 : struct TALER_JSON_ProtocolVersion *ver)
1971 : {
1972 55 : struct GNUNET_JSON_Specification ret = {
1973 : .parser = &parse_protocol_version,
1974 : .field = field,
1975 : .ptr = ver
1976 : };
1977 :
1978 55 : return ret;
1979 : }
1980 :
1981 :
1982 : /**
1983 : * Parse given JSON object to an OTP key.
1984 : *
1985 : * @param cls closure, NULL
1986 : * @param root the json object representing data
1987 : * @param[out] spec where to write the data
1988 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1989 : */
1990 : static enum GNUNET_GenericReturnValue
1991 0 : parse_otp_key (void *cls,
1992 : json_t *root,
1993 : struct GNUNET_JSON_Specification *spec)
1994 : {
1995 : const char *pos_key;
1996 :
1997 : (void) cls;
1998 0 : pos_key = json_string_value (root);
1999 0 : if (NULL == pos_key)
2000 : {
2001 0 : GNUNET_break_op (0);
2002 0 : return GNUNET_SYSERR;
2003 : }
2004 : {
2005 0 : size_t pos_key_length = strlen (pos_key);
2006 : void *key; /* pos_key in binary */
2007 : size_t key_len; /* length of the key */
2008 : int dret;
2009 :
2010 0 : key_len = pos_key_length * 5 / 8;
2011 0 : key = GNUNET_malloc (key_len);
2012 0 : dret = TALER_rfc3548_base32decode (pos_key,
2013 : pos_key_length,
2014 : key,
2015 : key_len);
2016 0 : if (-1 == dret)
2017 : {
2018 0 : GNUNET_free (key);
2019 0 : GNUNET_break_op (0);
2020 0 : return GNUNET_SYSERR;
2021 : }
2022 0 : GNUNET_free (key);
2023 : }
2024 0 : *(const char **) spec->ptr = pos_key;
2025 0 : return GNUNET_OK;
2026 : }
2027 :
2028 :
2029 : struct GNUNET_JSON_Specification
2030 0 : TALER_JSON_spec_otp_key (const char *name,
2031 : const char **otp_key)
2032 : {
2033 0 : struct GNUNET_JSON_Specification ret = {
2034 : .parser = &parse_otp_key,
2035 : .field = name,
2036 : .ptr = otp_key
2037 : };
2038 :
2039 0 : *otp_key = NULL;
2040 0 : return ret;
2041 : }
2042 :
2043 :
2044 : /**
2045 : * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm`
2046 : *
2047 : * @param cls closure, NULL
2048 : * @param root the json object representing data
2049 : * @param[out] spec where to write the data
2050 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
2051 : */
2052 : static enum GNUNET_GenericReturnValue
2053 0 : parse_otp_type (void *cls,
2054 : json_t *root,
2055 : struct GNUNET_JSON_Specification *spec)
2056 : {
2057 : static const struct Entry
2058 : {
2059 : const char *name;
2060 : enum TALER_MerchantConfirmationAlgorithm val;
2061 : } lt [] = {
2062 : { .name = "NONE",
2063 : .val = TALER_MCA_NONE },
2064 : { .name = "TOTP_WITHOUT_PRICE",
2065 : .val = TALER_MCA_WITHOUT_PRICE },
2066 : { .name = "TOTP_WITH_PRICE",
2067 : .val = TALER_MCA_WITH_PRICE },
2068 : { .name = "ECDSA_CHALLENGE",
2069 : .val = TALER_MCA_ECDSA_CHALLENGE },
2070 : { .name = "EDDSA_CHALLENGE",
2071 : .val = TALER_MCA_EDDSA_CHALLENGE },
2072 : { .name = NULL,
2073 : .val = TALER_MCA_NONE },
2074 : };
2075 0 : enum TALER_MerchantConfirmationAlgorithm *res
2076 : = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr;
2077 :
2078 : (void) cls;
2079 0 : if (json_is_string (root))
2080 : {
2081 : const char *str;
2082 :
2083 0 : str = json_string_value (root);
2084 0 : if (NULL == str)
2085 : {
2086 0 : GNUNET_break_op (0);
2087 0 : return GNUNET_SYSERR;
2088 : }
2089 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2090 : {
2091 0 : if (0 == strcasecmp (str,
2092 0 : lt[i].name))
2093 : {
2094 0 : *res = lt[i].val;
2095 0 : return GNUNET_OK;
2096 : }
2097 : }
2098 0 : GNUNET_break_op (0);
2099 : }
2100 0 : if (json_is_integer (root))
2101 : {
2102 : json_int_t val;
2103 :
2104 0 : val = json_integer_value (root);
2105 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2106 : {
2107 0 : if (val == lt[i].val)
2108 : {
2109 0 : *res = lt[i].val;
2110 0 : return GNUNET_OK;
2111 : }
2112 : }
2113 0 : GNUNET_break_op (0);
2114 0 : return GNUNET_SYSERR;
2115 : }
2116 0 : GNUNET_break_op (0);
2117 0 : return GNUNET_SYSERR;
2118 : }
2119 :
2120 :
2121 : struct GNUNET_JSON_Specification
2122 0 : TALER_JSON_spec_otp_type (const char *name,
2123 : enum TALER_MerchantConfirmationAlgorithm *mca)
2124 : {
2125 0 : struct GNUNET_JSON_Specification ret = {
2126 : .parser = &parse_otp_type,
2127 : .field = name,
2128 : .ptr = mca
2129 : };
2130 :
2131 0 : *mca = TALER_MCA_NONE;
2132 0 : return ret;
2133 : }
2134 :
2135 :
2136 : /**
2137 : * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent`
2138 : *
2139 : * @param cls closure, NULL
2140 : * @param root the json object representing data
2141 : * @param[out] spec where to write the data
2142 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
2143 : */
2144 : static enum GNUNET_GenericReturnValue
2145 314 : parse_kycte (void *cls,
2146 : json_t *root,
2147 : struct GNUNET_JSON_Specification *spec)
2148 : {
2149 : static const struct Entry
2150 : {
2151 : const char *name;
2152 : enum TALER_KYCLOGIC_KycTriggerEvent val;
2153 : } lt [] = {
2154 : { .name = "NONE",
2155 : .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
2156 : { .name = "WITHDRAW",
2157 : .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
2158 : { .name = "DEPOSIT",
2159 : .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
2160 : { .name = "MERGE",
2161 : .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
2162 : { .name = "BALANCE",
2163 : .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
2164 : { .name = "CLOSE",
2165 : .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
2166 : { .name = "AGGREGATE",
2167 : .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
2168 : { .name = "TRANSACTION",
2169 : .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
2170 : { .name = "REFUND",
2171 : .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
2172 : { .name = NULL,
2173 : .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
2174 : };
2175 314 : enum TALER_KYCLOGIC_KycTriggerEvent *res
2176 : = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr;
2177 :
2178 : (void) cls;
2179 314 : if (json_is_string (root))
2180 : {
2181 : const char *str;
2182 :
2183 314 : str = json_string_value (root);
2184 314 : if (NULL == str)
2185 : {
2186 0 : GNUNET_break_op (0);
2187 0 : return GNUNET_SYSERR;
2188 : }
2189 1461 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2190 : {
2191 1461 : if (0 == strcasecmp (str,
2192 1461 : lt[i].name))
2193 : {
2194 314 : *res = lt[i].val;
2195 314 : return GNUNET_OK;
2196 : }
2197 : }
2198 0 : GNUNET_break_op (0);
2199 0 : return GNUNET_SYSERR;
2200 : }
2201 0 : if (json_is_integer (root))
2202 : {
2203 : json_int_t val;
2204 :
2205 0 : val = json_integer_value (root);
2206 0 : for (unsigned int i = 0; NULL != lt[i].name; i++)
2207 : {
2208 0 : if (val == lt[i].val)
2209 : {
2210 0 : *res = lt[i].val;
2211 0 : return GNUNET_OK;
2212 : }
2213 : }
2214 0 : GNUNET_break_op (0);
2215 0 : return GNUNET_SYSERR;
2216 : }
2217 0 : GNUNET_break_op (0);
2218 0 : return GNUNET_SYSERR;
2219 : }
2220 :
2221 :
2222 : struct GNUNET_JSON_Specification
2223 315 : TALER_JSON_spec_kycte (const char *name,
2224 : enum TALER_KYCLOGIC_KycTriggerEvent *kte)
2225 : {
2226 315 : struct GNUNET_JSON_Specification ret = {
2227 : .parser = &parse_kycte,
2228 : .field = name,
2229 : .ptr = kte
2230 : };
2231 :
2232 315 : *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE;
2233 315 : return ret;
2234 : }
2235 :
2236 :
2237 : /**
2238 : * Parser combinator of a tuple of parsers, for parsing
2239 : * an array of expected size and element types.
2240 : *
2241 : * @param cls closure, array of specs, NULL terminated
2242 : * @param root the json root
2243 : * @param[out] spec where to write the data
2244 : */
2245 : static enum GNUNET_GenericReturnValue
2246 156 : parse_tuple_of (void *cls,
2247 : json_t *root,
2248 : struct GNUNET_JSON_Specification *spec)
2249 : {
2250 156 : struct GNUNET_JSON_Specification *specs = cls;
2251 : static size_t max_specs = 100;
2252 156 : bool found_end = false;
2253 :
2254 : enum GNUNET_GenericReturnValue ret;
2255 :
2256 156 : if (! json_is_array (root))
2257 : {
2258 0 : return GNUNET_SYSERR;
2259 : }
2260 :
2261 : {
2262 : size_t num;
2263 468 : for (num = 0; num< max_specs; num++)
2264 : {
2265 468 : if (NULL == specs[num].parser)
2266 : {
2267 156 : found_end = true;
2268 156 : break;
2269 : }
2270 : }
2271 156 : GNUNET_assert (found_end);
2272 :
2273 156 : if (num != json_array_size (root))
2274 : {
2275 0 : GNUNET_break_op (0);
2276 0 : return GNUNET_SYSERR;
2277 : }
2278 : }
2279 :
2280 : {
2281 : json_t *j_entry;
2282 : size_t idx;
2283 :
2284 468 : json_array_foreach (root, idx, j_entry) {
2285 312 : ret = GNUNET_JSON_parse (j_entry,
2286 312 : &specs[idx],
2287 : NULL,
2288 : NULL);
2289 312 : if (GNUNET_OK != ret)
2290 : {
2291 0 : GNUNET_break_op (0);
2292 0 : return GNUNET_SYSERR;
2293 : }
2294 : }
2295 : }
2296 :
2297 156 : return GNUNET_OK;
2298 : }
2299 :
2300 :
2301 : struct GNUNET_JSON_Specification
2302 178 : TALER_JSON_spec_tuple_of (
2303 : const char *field,
2304 : struct GNUNET_JSON_Specification specs[])
2305 : {
2306 178 : struct GNUNET_JSON_Specification ret = {
2307 : .parser = &parse_tuple_of,
2308 : .field = field,
2309 : .cls = specs
2310 : };
2311 :
2312 178 : return ret;
2313 : }
2314 :
2315 :
2316 : /**
2317 : * Parser for an array of unknown length but
2318 : * of elements of the same type with the same
2319 : * fixed length.
2320 : *
2321 : * @param cls closure, entry_size
2322 : * @param root the json root
2323 : * @param spec the output spec
2324 : */
2325 : static enum GNUNET_GenericReturnValue
2326 168 : parse_array_fixed (void *cls,
2327 : json_t *root,
2328 : struct GNUNET_JSON_Specification *spec)
2329 : {
2330 : enum GNUNET_GenericReturnValue ret;
2331 168 : size_t entry_size = (size_t) cls;
2332 : size_t num_entries;
2333 :
2334 168 : GNUNET_assert (0< entry_size);
2335 168 : num_entries = spec->ptr_size / entry_size;
2336 168 : GNUNET_assert (0 < num_entries);
2337 :
2338 :
2339 168 : if (! json_is_array (root))
2340 : {
2341 0 : GNUNET_break_op (0);
2342 0 : return GNUNET_SYSERR;
2343 : }
2344 168 : if (num_entries != json_array_size (root))
2345 : {
2346 0 : GNUNET_break_op (0);
2347 0 : return GNUNET_SYSERR;
2348 : }
2349 :
2350 : {
2351 : json_t *j_entry;
2352 : size_t idx;
2353 168 : void *ptr = spec->ptr;
2354 168 : void *end = spec->ptr + spec->ptr_size;
2355 :
2356 624 : json_array_foreach (root, idx, j_entry) {
2357 : struct GNUNET_JSON_Specification esp[] = {
2358 456 : GNUNET_JSON_spec_fixed (NULL,
2359 : ptr,
2360 : entry_size),
2361 456 : GNUNET_JSON_spec_end ()
2362 : };
2363 456 : GNUNET_assert (ptr < end);
2364 456 : ret = GNUNET_JSON_parse (j_entry,
2365 : esp,
2366 : NULL,
2367 : NULL);
2368 456 : if (GNUNET_OK != ret)
2369 : {
2370 0 : GNUNET_break_op (0);
2371 0 : return GNUNET_SYSERR;
2372 : }
2373 456 : ptr += entry_size;
2374 : }
2375 : }
2376 168 : return GNUNET_OK;
2377 : }
2378 :
2379 :
2380 : struct GNUNET_JSON_Specification
2381 168 : TALER_JSON_spec_array_fixed (
2382 : const char *field,
2383 : size_t num_entries,
2384 : void *entries,
2385 : size_t entry_size)
2386 : {
2387 168 : struct GNUNET_JSON_Specification ret = {
2388 : .parser = &parse_array_fixed,
2389 : .ptr = entries,
2390 168 : .ptr_size = entry_size * num_entries,
2391 : .field = field,
2392 168 : .cls = (void *) entry_size,
2393 : };
2394 :
2395 168 : GNUNET_assert ((num_entries <= 1) ||
2396 : (entry_size * num_entries > entry_size));
2397 168 : return ret;
2398 : }
2399 :
2400 :
2401 : /**
2402 : * Closure for the parser of arrays of fixed size data
2403 : * of unknown array length
2404 : */
2405 : struct closure_array_of_data
2406 : {
2407 : /**
2408 : * Fixed (known) size per entry
2409 : */
2410 : size_t entry_size;
2411 :
2412 : /**
2413 : * Pointer where to put the number of elements
2414 : * allocated, i.e. the number of elements in the
2415 : * json array.
2416 : */
2417 : size_t *num_entries;
2418 : };
2419 :
2420 : /**
2421 : * Parser for an array of data of known element size,
2422 : * but unknown array length
2423 : */
2424 : static enum GNUNET_GenericReturnValue
2425 10 : parse_array_of_data (void *cls,
2426 : json_t *root,
2427 : struct GNUNET_JSON_Specification *spec)
2428 : {
2429 : enum GNUNET_GenericReturnValue ret;
2430 10 : struct closure_array_of_data *info = cls;
2431 : size_t num_entries;
2432 :
2433 10 : if (! json_is_array (root))
2434 : {
2435 0 : GNUNET_break_op (0);
2436 0 : return GNUNET_SYSERR;
2437 : }
2438 10 : num_entries = json_array_size (root);
2439 10 : *info->num_entries = num_entries;
2440 10 : if (0 == num_entries)
2441 : {
2442 0 : *(char **) spec->ptr = NULL;
2443 0 : return GNUNET_OK;
2444 : }
2445 :
2446 10 : spec->ptr_size = num_entries * info->entry_size;
2447 10 : GNUNET_assert (spec->ptr_size > num_entries);
2448 10 : *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size);
2449 :
2450 : {
2451 : json_t *j_entry;
2452 : size_t idx;
2453 10 : char *ptr = *(char **) spec->ptr;
2454 10 : char *end = ptr + spec->ptr_size;
2455 :
2456 33 : json_array_foreach (root, idx, j_entry) {
2457 : struct GNUNET_JSON_Specification esp[] = {
2458 23 : GNUNET_JSON_spec_fixed (NULL,
2459 : ptr,
2460 : info->entry_size),
2461 23 : GNUNET_JSON_spec_end ()
2462 : };
2463 23 : GNUNET_assert (ptr < end);
2464 23 : ret = GNUNET_JSON_parse (j_entry,
2465 : esp,
2466 : NULL,
2467 : NULL);
2468 23 : if (GNUNET_OK != ret)
2469 : {
2470 0 : GNUNET_break_op (0);
2471 0 : return GNUNET_SYSERR;
2472 : }
2473 23 : ptr += info->entry_size;
2474 : }
2475 : }
2476 10 : return GNUNET_OK;
2477 : }
2478 :
2479 :
2480 : /**
2481 : * Cleanup data left from parsing an array of fixed size (but unknown length).
2482 : *
2483 : * @param cls closure_of_array_data
2484 : * @param[out] spec where to free the data
2485 : */
2486 : static void
2487 9 : cleaner_array_of_data (void *cls,
2488 : struct GNUNET_JSON_Specification *spec)
2489 : {
2490 9 : struct closure_array_of_data *info = cls;
2491 :
2492 9 : GNUNET_free (*(void **) spec->ptr);
2493 9 : GNUNET_free (info);
2494 9 : }
2495 :
2496 :
2497 : struct GNUNET_JSON_Specification
2498 10 : TALER_JSON_spec_array_of_data (
2499 : const char *field,
2500 : size_t entry_size,
2501 : size_t *num_entries,
2502 : void **entries)
2503 : {
2504 : struct closure_array_of_data *cls;
2505 :
2506 10 : GNUNET_assert (0< entry_size);
2507 10 : *entries = NULL;
2508 10 : *num_entries = 0;
2509 10 : cls = GNUNET_new (struct closure_array_of_data);
2510 10 : cls->num_entries = num_entries;
2511 10 : cls->entry_size = entry_size;
2512 : {
2513 10 : struct GNUNET_JSON_Specification ret = {
2514 : .parser = &parse_array_of_data,
2515 : .ptr = entries,
2516 : .field = field,
2517 : .cleaner = &cleaner_array_of_data,
2518 : .cls = (void *) cls,
2519 : };
2520 :
2521 10 : return ret;
2522 : }
2523 : }
2524 :
2525 :
2526 : struct GNUNET_JSON_Specification
2527 9 : TALER_JSON_spec_array_of_denom_pub_h (
2528 : const char *field,
2529 : size_t *num_entries,
2530 : struct TALER_DenominationHashP **entries)
2531 : {
2532 9 : *num_entries = 0;
2533 9 : *entries = NULL;
2534 9 : return TALER_JSON_spec_array_of_data (
2535 : field,
2536 : sizeof (struct TALER_DenominationHashP),
2537 : num_entries,
2538 : (void **) entries);
2539 : }
2540 :
2541 :
2542 : /**
2543 : * Parser for an array of blinded denomination signatures,
2544 : * of unknown array length
2545 : */
2546 : static enum GNUNET_GenericReturnValue
2547 22 : parse_array_of_blinded_denom_sigs (void *cls,
2548 : json_t *root,
2549 : struct GNUNET_JSON_Specification *spec)
2550 : {
2551 : enum GNUNET_GenericReturnValue ret;
2552 22 : struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
2553 22 : size_t expected_num_entries = (size_t) cls;
2554 : size_t num_entries;
2555 :
2556 22 : if (! json_is_array (root))
2557 : {
2558 0 : GNUNET_break_op (0);
2559 0 : return GNUNET_SYSERR;
2560 : }
2561 22 : num_entries = json_array_size (root);
2562 22 : if (num_entries != expected_num_entries)
2563 : {
2564 0 : GNUNET_break_op (0);
2565 0 : return GNUNET_SYSERR;
2566 : }
2567 :
2568 : {
2569 : json_t *j_entry;
2570 : size_t idx;
2571 22 : struct TALER_BlindedDenominationSignature *ptr = sigs;
2572 :
2573 92 : json_array_foreach (root, idx, j_entry) {
2574 : struct GNUNET_JSON_Specification esp[] = {
2575 70 : TALER_JSON_spec_blinded_denom_sig (NULL,
2576 : ptr),
2577 70 : GNUNET_JSON_spec_end ()
2578 : };
2579 70 : ret = GNUNET_JSON_parse (j_entry,
2580 : esp,
2581 : NULL,
2582 : NULL);
2583 70 : if (GNUNET_OK != ret)
2584 : {
2585 0 : GNUNET_break_op (0);
2586 0 : for (size_t i = 0; i < idx; i++)
2587 : {
2588 0 : TALER_blinded_denom_sig_free (&sigs[i]);
2589 0 : sigs[i].blinded_sig = NULL;
2590 : }
2591 0 : return GNUNET_SYSERR;
2592 : }
2593 70 : ptr++;
2594 : }
2595 : }
2596 22 : return GNUNET_OK;
2597 : }
2598 :
2599 :
2600 : /**
2601 : * Cleanup data left from parsing an array of blinded signatures.
2602 : *
2603 : * @param cls pointer to a size_t with the length of the array
2604 : * @param[out] spec where to free the data
2605 : */
2606 : static void
2607 22 : cleaner_array_of_blinded_denom_sigs (
2608 : void *cls,
2609 : struct GNUNET_JSON_Specification *spec)
2610 : {
2611 22 : struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
2612 22 : size_t num_entries = (size_t) cls;
2613 :
2614 92 : for (size_t i = 0; i < num_entries; i++)
2615 : {
2616 70 : if (NULL != sigs[i].blinded_sig)
2617 : {
2618 70 : TALER_blinded_denom_sig_free (&sigs[i]);
2619 70 : sigs[i].blinded_sig = NULL;
2620 : }
2621 : }
2622 22 : }
2623 :
2624 :
2625 : struct GNUNET_JSON_Specification
2626 22 : TALER_JSON_spec_array_of_blinded_denom_sigs (
2627 : const char *field,
2628 : size_t num_entries,
2629 : struct TALER_BlindedDenominationSignature *entries)
2630 : {
2631 22 : struct GNUNET_JSON_Specification ret = {
2632 : .parser = &parse_array_of_blinded_denom_sigs,
2633 : .ptr = entries,
2634 : .field = field,
2635 : .cleaner = &cleaner_array_of_blinded_denom_sigs,
2636 22 : .cls = (void *) num_entries,
2637 : };
2638 :
2639 92 : for (size_t i = 0; i<num_entries; i++)
2640 70 : entries[i].blinded_sig = NULL;
2641 22 : return ret;
2642 : }
2643 :
2644 :
2645 : /* end of json/json_helper.c */
|