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