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