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