Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2021 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 "platform.h"
24 : #include <gnunet/gnunet_util_lib.h>
25 : #include "taler_util.h"
26 : #include "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 TALER_DenominationCipher
36 0 : string_to_cipher (const char *cipher_s)
37 : {
38 0 : if ((0 == strcasecmp (cipher_s,
39 0 : "RSA")) ||
40 0 : (0 == strcasecmp (cipher_s,
41 : "RSA+age_restricted")))
42 0 : return TALER_DENOMINATION_RSA;
43 0 : if ((0 == strcasecmp (cipher_s,
44 0 : "CS")) ||
45 0 : (0 == strcasecmp (cipher_s,
46 : "CS+age_restricted")))
47 0 : return TALER_DENOMINATION_CS;
48 0 : return TALER_DENOMINATION_INVALID;
49 : }
50 :
51 :
52 : json_t *
53 17 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
54 : {
55 17 : char *amount_str = TALER_amount_to_string (amount);
56 :
57 17 : GNUNET_assert (NULL != amount_str);
58 : {
59 17 : json_t *j = json_string (amount_str);
60 :
61 17 : GNUNET_free (amount_str);
62 17 : return j;
63 : }
64 : }
65 :
66 :
67 : json_t *
68 0 : TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO *amount)
69 : {
70 : struct TALER_Amount a;
71 :
72 0 : TALER_amount_ntoh (&a,
73 : amount);
74 0 : return TALER_JSON_from_amount (&a);
75 : }
76 :
77 :
78 : /**
79 : * Parse given JSON object to Amount
80 : *
81 : * @param cls closure, expected currency, or NULL
82 : * @param root the json object representing data
83 : * @param[out] spec where to write the data
84 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
85 : */
86 : static enum GNUNET_GenericReturnValue
87 15 : parse_amount (void *cls,
88 : json_t *root,
89 : struct GNUNET_JSON_Specification *spec)
90 : {
91 15 : const char *currency = cls;
92 15 : struct TALER_Amount *r_amount = spec->ptr;
93 :
94 : (void) cls;
95 15 : if (! json_is_string (root))
96 : {
97 0 : GNUNET_break_op (0);
98 0 : return GNUNET_SYSERR;
99 : }
100 15 : if (GNUNET_OK !=
101 15 : TALER_string_to_amount (json_string_value (root),
102 : r_amount))
103 : {
104 0 : GNUNET_break_op (0);
105 0 : return GNUNET_SYSERR;
106 : }
107 15 : if ( (NULL != currency) &&
108 : (0 !=
109 9 : strcasecmp (currency,
110 9 : r_amount->currency)) )
111 : {
112 0 : GNUNET_break_op (0);
113 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
114 : "Expected currency `%s', but amount used currency `%s' in field `%s'\n",
115 : currency,
116 : r_amount->currency,
117 : spec->field);
118 0 : return GNUNET_SYSERR;
119 : }
120 15 : return GNUNET_OK;
121 : }
122 :
123 :
124 : struct GNUNET_JSON_Specification
125 9 : TALER_JSON_spec_amount (const char *name,
126 : const char *currency,
127 : struct TALER_Amount *r_amount)
128 : {
129 9 : struct GNUNET_JSON_Specification ret = {
130 : .parser = &parse_amount,
131 : .cleaner = NULL,
132 : .cls = (void *) currency,
133 : .field = name,
134 : .ptr = r_amount,
135 : .ptr_size = 0,
136 : .size_ptr = NULL
137 : };
138 :
139 9 : GNUNET_assert (NULL != currency);
140 9 : return ret;
141 : }
142 :
143 :
144 : struct GNUNET_JSON_Specification
145 6 : TALER_JSON_spec_amount_any (const char *name,
146 : struct TALER_Amount *r_amount)
147 : {
148 6 : struct GNUNET_JSON_Specification ret = {
149 : .parser = &parse_amount,
150 : .cleaner = NULL,
151 : .cls = NULL,
152 : .field = name,
153 : .ptr = r_amount,
154 : .ptr_size = 0,
155 : .size_ptr = NULL
156 : };
157 :
158 6 : return ret;
159 : }
160 :
161 :
162 : /**
163 : * Parse given JSON object to Amount in NBO.
164 : *
165 : * @param cls closure, NULL
166 : * @param root the json object representing data
167 : * @param[out] spec where to write the data
168 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
169 : */
170 : static enum GNUNET_GenericReturnValue
171 0 : parse_amount_nbo (void *cls,
172 : json_t *root,
173 : struct GNUNET_JSON_Specification *spec)
174 : {
175 0 : const char *currency = cls;
176 0 : struct TALER_AmountNBO *r_amount = spec->ptr;
177 : const char *sv;
178 :
179 : (void) cls;
180 0 : if (! json_is_string (root))
181 : {
182 0 : GNUNET_break (0);
183 0 : return GNUNET_SYSERR;
184 : }
185 0 : sv = json_string_value (root);
186 0 : if (GNUNET_OK !=
187 0 : TALER_string_to_amount_nbo (sv,
188 : r_amount))
189 : {
190 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
191 : "`%s' is not a valid amount\n",
192 : sv);
193 0 : GNUNET_break_op (0);
194 0 : return GNUNET_SYSERR;
195 : }
196 0 : if ( (NULL != currency) &&
197 : (0 !=
198 0 : strcasecmp (currency,
199 0 : r_amount->currency)) )
200 : {
201 0 : GNUNET_break_op (0);
202 0 : return GNUNET_SYSERR;
203 : }
204 0 : return GNUNET_OK;
205 : }
206 :
207 :
208 : struct GNUNET_JSON_Specification
209 0 : TALER_JSON_spec_amount_nbo (const char *name,
210 : const char *currency,
211 : struct TALER_AmountNBO *r_amount)
212 : {
213 0 : struct GNUNET_JSON_Specification ret = {
214 : .parser = &parse_amount_nbo,
215 : .cleaner = NULL,
216 : .cls = (void *) currency,
217 : .field = name,
218 : .ptr = r_amount,
219 : .ptr_size = 0,
220 : .size_ptr = NULL
221 : };
222 :
223 0 : GNUNET_assert (NULL != currency);
224 0 : return ret;
225 : }
226 :
227 :
228 : struct GNUNET_JSON_Specification
229 0 : TALER_JSON_spec_amount_any_nbo (const char *name,
230 : struct TALER_AmountNBO *r_amount)
231 : {
232 0 : struct GNUNET_JSON_Specification ret = {
233 : .parser = &parse_amount_nbo,
234 : .cleaner = NULL,
235 : .cls = NULL,
236 : .field = name,
237 : .ptr = r_amount,
238 : .ptr_size = 0,
239 : .size_ptr = NULL
240 : };
241 :
242 0 : return ret;
243 : }
244 :
245 :
246 : static enum GNUNET_GenericReturnValue
247 0 : parse_denomination_group (void *cls,
248 : json_t *root,
249 : struct GNUNET_JSON_Specification *spec)
250 : {
251 0 : struct TALER_DenominationGroup *group = spec->ptr;
252 : const char *cipher;
253 0 : const char *currency = cls;
254 0 : bool age_mask_missing = false;
255 0 : bool has_age_restricted_suffix = false;
256 : struct GNUNET_JSON_Specification gspec[] = {
257 0 : GNUNET_JSON_spec_string ("cipher",
258 : &cipher),
259 0 : TALER_JSON_spec_amount ("value",
260 : currency,
261 : &group->value),
262 0 : TALER_JSON_SPEC_DENOM_FEES ("fee",
263 : currency,
264 : &group->fees),
265 0 : GNUNET_JSON_spec_mark_optional (
266 : GNUNET_JSON_spec_uint32 ("age_mask",
267 : &group->age_mask.bits),
268 : &age_mask_missing),
269 0 : GNUNET_JSON_spec_fixed_auto ("hash",
270 : &group->hash),
271 0 : GNUNET_JSON_spec_end ()
272 : };
273 : const char *emsg;
274 : unsigned int eline;
275 :
276 0 : if (GNUNET_OK !=
277 0 : GNUNET_JSON_parse (root,
278 : gspec,
279 : &emsg,
280 : &eline))
281 : {
282 0 : GNUNET_break_op (0);
283 0 : return GNUNET_SYSERR;
284 : }
285 :
286 0 : group->cipher = string_to_cipher (cipher);
287 0 : if (TALER_DENOMINATION_INVALID == group->cipher)
288 : {
289 0 : GNUNET_break_op (0);
290 0 : return GNUNET_SYSERR;
291 : }
292 :
293 : /* age_mask and suffix must be consistent */
294 0 : has_age_restricted_suffix =
295 0 : (NULL != strstr (cipher, "+age_restricted"));
296 0 : if (has_age_restricted_suffix && age_mask_missing)
297 : {
298 0 : GNUNET_break_op (0);
299 0 : return GNUNET_SYSERR;
300 : }
301 :
302 0 : if (age_mask_missing)
303 0 : group->age_mask.bits = 0;
304 :
305 0 : return GNUNET_OK;
306 : }
307 :
308 :
309 : struct GNUNET_JSON_Specification
310 0 : TALER_JSON_spec_denomination_group (const char *name,
311 : const char *currency,
312 : struct TALER_DenominationGroup *group)
313 : {
314 0 : struct GNUNET_JSON_Specification ret = {
315 : .cls = (void *) currency,
316 : .parser = &parse_denomination_group,
317 : .cleaner = NULL,
318 : .field = name,
319 : .ptr = group,
320 : .ptr_size = sizeof(*group),
321 : .size_ptr = NULL,
322 : };
323 :
324 0 : return ret;
325 : }
326 :
327 :
328 : /**
329 : * Parse given JSON object to an encrypted contract.
330 : *
331 : * @param cls closure, NULL
332 : * @param root the json object representing data
333 : * @param[out] spec where to write the data
334 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
335 : */
336 : static enum GNUNET_GenericReturnValue
337 0 : parse_econtract (void *cls,
338 : json_t *root,
339 : struct GNUNET_JSON_Specification *spec)
340 : {
341 0 : struct TALER_EncryptedContract *econtract = spec->ptr;
342 : struct GNUNET_JSON_Specification ispec[] = {
343 0 : GNUNET_JSON_spec_varsize ("econtract",
344 : &econtract->econtract,
345 : &econtract->econtract_size),
346 0 : GNUNET_JSON_spec_fixed_auto ("econtract_sig",
347 : &econtract->econtract_sig),
348 0 : GNUNET_JSON_spec_fixed_auto ("contract_pub",
349 : &econtract->contract_pub),
350 0 : GNUNET_JSON_spec_end ()
351 : };
352 : const char *emsg;
353 : unsigned int eline;
354 :
355 : (void) cls;
356 0 : if (GNUNET_OK !=
357 0 : GNUNET_JSON_parse (root,
358 : ispec,
359 : &emsg,
360 : &eline))
361 : {
362 0 : GNUNET_break_op (0);
363 0 : return GNUNET_SYSERR;
364 : }
365 0 : return GNUNET_OK;
366 : }
367 :
368 :
369 : /**
370 : * Cleanup data left from parsing encrypted contract.
371 : *
372 : * @param cls closure, NULL
373 : * @param[out] spec where to free the data
374 : */
375 : static void
376 0 : clean_econtract (void *cls,
377 : struct GNUNET_JSON_Specification *spec)
378 : {
379 0 : struct TALER_EncryptedContract *econtract = spec->ptr;
380 :
381 : (void) cls;
382 0 : GNUNET_free (econtract->econtract);
383 0 : }
384 :
385 :
386 : struct GNUNET_JSON_Specification
387 0 : TALER_JSON_spec_econtract (const char *name,
388 : struct TALER_EncryptedContract *econtract)
389 : {
390 0 : struct GNUNET_JSON_Specification ret = {
391 : .parser = &parse_econtract,
392 : .cleaner = &clean_econtract,
393 : .cls = NULL,
394 : .field = name,
395 : .ptr = econtract,
396 : .ptr_size = 0,
397 : .size_ptr = NULL
398 : };
399 :
400 0 : return ret;
401 : }
402 :
403 :
404 : /**
405 : * Parse given JSON object to an age commitmnet
406 : *
407 : * @param cls closure, NULL
408 : * @param root the json object representing data
409 : * @param[out] spec where to write the data
410 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
411 : */
412 : static enum GNUNET_GenericReturnValue
413 0 : parse_age_commitment (void *cls,
414 : json_t *root,
415 : struct GNUNET_JSON_Specification *spec)
416 : {
417 0 : struct TALER_AgeCommitment *age_commitment = spec->ptr;
418 : json_t *pk;
419 : unsigned int idx;
420 : size_t num;
421 :
422 : (void) cls;
423 0 : if ( (NULL == root) ||
424 0 : (! json_is_array (root)))
425 : {
426 0 : GNUNET_break_op (0);
427 0 : return GNUNET_SYSERR;
428 : }
429 :
430 0 : num = json_array_size (root);
431 0 : if (32 <= num || 0 == num)
432 : {
433 0 : GNUNET_break_op (0);
434 0 : return GNUNET_SYSERR;
435 : }
436 :
437 0 : age_commitment->num = num;
438 0 : age_commitment->keys =
439 0 : GNUNET_new_array (num,
440 : struct TALER_AgeCommitmentPublicKeyP);
441 :
442 0 : json_array_foreach (root, idx, pk) {
443 : const char *emsg;
444 : unsigned int eline;
445 : struct GNUNET_JSON_Specification pkspec[] = {
446 0 : GNUNET_JSON_spec_fixed_auto (
447 : NULL,
448 : &age_commitment->keys[idx].pub),
449 0 : GNUNET_JSON_spec_end ()
450 : };
451 :
452 0 : if (GNUNET_OK !=
453 0 : GNUNET_JSON_parse (pk,
454 : pkspec,
455 : &emsg,
456 : &eline))
457 : {
458 0 : GNUNET_break_op (0);
459 0 : GNUNET_JSON_parse_free (spec);
460 0 : return GNUNET_SYSERR;
461 : }
462 : };
463 :
464 0 : return GNUNET_OK;
465 : }
466 :
467 :
468 : /**
469 : * Cleanup data left fom parsing age commitment
470 : *
471 : * @param cls closure, NULL
472 : * @param[out] spec where to free the data
473 : */
474 : static void
475 0 : clean_age_commitment (void *cls,
476 : struct GNUNET_JSON_Specification *spec)
477 : {
478 0 : struct TALER_AgeCommitment *age_commitment = spec->ptr;
479 :
480 : (void) cls;
481 :
482 0 : if (NULL == age_commitment ||
483 0 : NULL == age_commitment->keys)
484 0 : return;
485 :
486 0 : age_commitment->num = 0;
487 0 : GNUNET_free (age_commitment->keys);
488 : }
489 :
490 :
491 : struct GNUNET_JSON_Specification
492 0 : TALER_JSON_spec_age_commitment (const char *name,
493 : struct TALER_AgeCommitment *age_commitment)
494 : {
495 0 : struct GNUNET_JSON_Specification ret = {
496 : .parser = &parse_age_commitment,
497 : .cleaner = &clean_age_commitment,
498 : .cls = NULL,
499 : .field = name,
500 : .ptr = age_commitment,
501 : .ptr_size = 0,
502 : .size_ptr = NULL
503 : };
504 :
505 0 : return ret;
506 : }
507 :
508 :
509 : /**
510 : * Parse given JSON object to denomination public key.
511 : *
512 : * @param cls closure, NULL
513 : * @param root the json object representing data
514 : * @param[out] spec where to write the data
515 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
516 : */
517 : static enum GNUNET_GenericReturnValue
518 0 : parse_denom_pub (void *cls,
519 : json_t *root,
520 : struct GNUNET_JSON_Specification *spec)
521 : {
522 0 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
523 : const char *cipher;
524 0 : bool age_mask_missing = false;
525 : struct GNUNET_JSON_Specification dspec[] = {
526 0 : GNUNET_JSON_spec_string ("cipher",
527 : &cipher),
528 0 : GNUNET_JSON_spec_mark_optional (
529 : GNUNET_JSON_spec_uint32 ("age_mask",
530 : &denom_pub->age_mask.bits),
531 : &age_mask_missing),
532 0 : GNUNET_JSON_spec_end ()
533 : };
534 : const char *emsg;
535 : unsigned int eline;
536 :
537 : (void) cls;
538 0 : if (GNUNET_OK !=
539 0 : GNUNET_JSON_parse (root,
540 : dspec,
541 : &emsg,
542 : &eline))
543 : {
544 0 : GNUNET_break_op (0);
545 0 : return GNUNET_SYSERR;
546 : }
547 :
548 0 : if (age_mask_missing)
549 0 : denom_pub->age_mask.bits = 0;
550 :
551 0 : denom_pub->cipher = string_to_cipher (cipher);
552 0 : switch (denom_pub->cipher)
553 : {
554 0 : case TALER_DENOMINATION_RSA:
555 : {
556 : struct GNUNET_JSON_Specification ispec[] = {
557 0 : GNUNET_JSON_spec_rsa_public_key (
558 : "rsa_public_key",
559 : &denom_pub->details.rsa_public_key),
560 0 : GNUNET_JSON_spec_end ()
561 : };
562 :
563 0 : if (GNUNET_OK !=
564 0 : GNUNET_JSON_parse (root,
565 : ispec,
566 : &emsg,
567 : &eline))
568 : {
569 0 : GNUNET_break_op (0);
570 0 : return GNUNET_SYSERR;
571 : }
572 0 : return GNUNET_OK;
573 : }
574 0 : case TALER_DENOMINATION_CS:
575 : {
576 : struct GNUNET_JSON_Specification ispec[] = {
577 0 : GNUNET_JSON_spec_fixed ("cs_public_key",
578 0 : &denom_pub->details.cs_public_key,
579 : sizeof (denom_pub->details.cs_public_key)),
580 0 : GNUNET_JSON_spec_end ()
581 : };
582 :
583 0 : if (GNUNET_OK !=
584 0 : GNUNET_JSON_parse (root,
585 : ispec,
586 : &emsg,
587 : &eline))
588 : {
589 0 : GNUNET_break_op (0);
590 0 : return GNUNET_SYSERR;
591 : }
592 0 : return GNUNET_OK;
593 : }
594 0 : default:
595 0 : GNUNET_break_op (0);
596 0 : return GNUNET_SYSERR;
597 : }
598 : }
599 :
600 :
601 : /**
602 : * Cleanup data left from parsing denomination public key.
603 : *
604 : * @param cls closure, NULL
605 : * @param[out] spec where to free the data
606 : */
607 : static void
608 0 : clean_denom_pub (void *cls,
609 : struct GNUNET_JSON_Specification *spec)
610 : {
611 0 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
612 :
613 : (void) cls;
614 0 : TALER_denom_pub_free (denom_pub);
615 0 : }
616 :
617 :
618 : struct GNUNET_JSON_Specification
619 0 : TALER_JSON_spec_denom_pub (const char *field,
620 : struct TALER_DenominationPublicKey *pk)
621 : {
622 0 : struct GNUNET_JSON_Specification ret = {
623 : .parser = &parse_denom_pub,
624 : .cleaner = &clean_denom_pub,
625 : .field = field,
626 : .ptr = pk
627 : };
628 :
629 0 : pk->cipher = TALER_DENOMINATION_INVALID;
630 0 : return ret;
631 : }
632 :
633 :
634 : /**
635 : * Parse given JSON object partially into a denomination public key.
636 : *
637 : * Depending on the cipher in cls, it parses the corresponding public key type.
638 : *
639 : * @param cls closure, enum TALER_DenominationCipher
640 : * @param root the json object representing data
641 : * @param[out] spec where to write the data
642 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
643 : */
644 : static enum GNUNET_GenericReturnValue
645 0 : parse_denom_pub_cipher (void *cls,
646 : json_t *root,
647 : struct GNUNET_JSON_Specification *spec)
648 : {
649 0 : struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
650 0 : enum TALER_DenominationCipher cipher =
651 0 : (enum TALER_DenominationCipher) (long) cls;
652 : const char *emsg;
653 : unsigned int eline;
654 :
655 0 : switch (cipher)
656 : {
657 0 : case TALER_DENOMINATION_RSA:
658 : {
659 : struct GNUNET_JSON_Specification ispec[] = {
660 0 : GNUNET_JSON_spec_rsa_public_key (
661 : "rsa_pub",
662 : &denom_pub->details.rsa_public_key),
663 0 : GNUNET_JSON_spec_end ()
664 : };
665 :
666 0 : if (GNUNET_OK !=
667 0 : GNUNET_JSON_parse (root,
668 : ispec,
669 : &emsg,
670 : &eline))
671 : {
672 0 : GNUNET_break_op (0);
673 0 : return GNUNET_SYSERR;
674 : }
675 0 : return GNUNET_OK;
676 : }
677 0 : case TALER_DENOMINATION_CS:
678 : {
679 : struct GNUNET_JSON_Specification ispec[] = {
680 0 : GNUNET_JSON_spec_fixed ("cs_pub",
681 0 : &denom_pub->details.cs_public_key,
682 : sizeof (denom_pub->details.cs_public_key)),
683 0 : GNUNET_JSON_spec_end ()
684 : };
685 :
686 0 : if (GNUNET_OK !=
687 0 : GNUNET_JSON_parse (root,
688 : ispec,
689 : &emsg,
690 : &eline))
691 : {
692 0 : GNUNET_break_op (0);
693 0 : return GNUNET_SYSERR;
694 : }
695 0 : return GNUNET_OK;
696 : }
697 0 : default:
698 0 : GNUNET_break_op (0);
699 0 : return GNUNET_SYSERR;
700 : }
701 : }
702 :
703 :
704 : struct GNUNET_JSON_Specification
705 0 : TALER_JSON_spec_denom_pub_cipher (const char *field,
706 : enum TALER_DenominationCipher cipher,
707 : struct TALER_DenominationPublicKey *pk)
708 : {
709 0 : struct GNUNET_JSON_Specification ret = {
710 : .parser = &parse_denom_pub_cipher,
711 : .cleaner = &clean_denom_pub,
712 : .field = field,
713 0 : .cls = (void *) cipher,
714 : .ptr = pk
715 : };
716 :
717 0 : return ret;
718 : }
719 :
720 :
721 : /**
722 : * Parse given JSON object to denomination signature.
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 0 : parse_denom_sig (void *cls,
731 : json_t *root,
732 : struct GNUNET_JSON_Specification *spec)
733 : {
734 0 : struct TALER_DenominationSignature *denom_sig = spec->ptr;
735 : const char *cipher;
736 : struct GNUNET_JSON_Specification dspec[] = {
737 0 : GNUNET_JSON_spec_string ("cipher",
738 : &cipher),
739 0 : GNUNET_JSON_spec_end ()
740 : };
741 : const char *emsg;
742 : unsigned int eline;
743 :
744 : (void) cls;
745 0 : if (GNUNET_OK !=
746 0 : GNUNET_JSON_parse (root,
747 : dspec,
748 : &emsg,
749 : &eline))
750 : {
751 0 : GNUNET_break_op (0);
752 0 : return GNUNET_SYSERR;
753 : }
754 0 : denom_sig->cipher = string_to_cipher (cipher);
755 0 : switch (denom_sig->cipher)
756 : {
757 0 : case TALER_DENOMINATION_RSA:
758 : {
759 : struct GNUNET_JSON_Specification ispec[] = {
760 0 : GNUNET_JSON_spec_rsa_signature (
761 : "rsa_signature",
762 : &denom_sig->details.rsa_signature),
763 0 : GNUNET_JSON_spec_end ()
764 : };
765 :
766 0 : if (GNUNET_OK !=
767 0 : GNUNET_JSON_parse (root,
768 : ispec,
769 : &emsg,
770 : &eline))
771 : {
772 0 : GNUNET_break_op (0);
773 0 : return GNUNET_SYSERR;
774 : }
775 0 : return GNUNET_OK;
776 : }
777 0 : case TALER_DENOMINATION_CS:
778 : {
779 : struct GNUNET_JSON_Specification ispec[] = {
780 0 : GNUNET_JSON_spec_fixed_auto ("cs_signature_r",
781 : &denom_sig->details.cs_signature.r_point),
782 0 : GNUNET_JSON_spec_fixed_auto ("cs_signature_s",
783 : &denom_sig->details.cs_signature.s_scalar),
784 0 : GNUNET_JSON_spec_end ()
785 : };
786 :
787 0 : if (GNUNET_OK !=
788 0 : GNUNET_JSON_parse (root,
789 : ispec,
790 : &emsg,
791 : &eline))
792 : {
793 0 : GNUNET_break_op (0);
794 0 : return GNUNET_SYSERR;
795 : }
796 0 : return GNUNET_OK;
797 : }
798 0 : default:
799 0 : GNUNET_break_op (0);
800 0 : return GNUNET_SYSERR;
801 : }
802 : }
803 :
804 :
805 : /**
806 : * Cleanup data left from parsing denomination public key.
807 : *
808 : * @param cls closure, NULL
809 : * @param[out] spec where to free the data
810 : */
811 : static void
812 0 : clean_denom_sig (void *cls,
813 : struct GNUNET_JSON_Specification *spec)
814 : {
815 0 : struct TALER_DenominationSignature *denom_sig = spec->ptr;
816 :
817 : (void) cls;
818 0 : TALER_denom_sig_free (denom_sig);
819 0 : }
820 :
821 :
822 : struct GNUNET_JSON_Specification
823 0 : TALER_JSON_spec_denom_sig (const char *field,
824 : struct TALER_DenominationSignature *sig)
825 : {
826 0 : struct GNUNET_JSON_Specification ret = {
827 : .parser = &parse_denom_sig,
828 : .cleaner = &clean_denom_sig,
829 : .field = field,
830 : .ptr = sig
831 : };
832 :
833 0 : sig->cipher = TALER_DENOMINATION_INVALID;
834 0 : return ret;
835 : }
836 :
837 :
838 : /**
839 : * Parse given JSON object to blinded denomination signature.
840 : *
841 : * @param cls closure, NULL
842 : * @param root the json object representing data
843 : * @param[out] spec where to write the data
844 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
845 : */
846 : static enum GNUNET_GenericReturnValue
847 0 : parse_blinded_denom_sig (void *cls,
848 : json_t *root,
849 : struct GNUNET_JSON_Specification *spec)
850 : {
851 0 : struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
852 : const char *cipher;
853 : struct GNUNET_JSON_Specification dspec[] = {
854 0 : GNUNET_JSON_spec_string ("cipher",
855 : &cipher),
856 0 : GNUNET_JSON_spec_end ()
857 : };
858 : const char *emsg;
859 : unsigned int eline;
860 :
861 : (void) cls;
862 0 : if (GNUNET_OK !=
863 0 : GNUNET_JSON_parse (root,
864 : dspec,
865 : &emsg,
866 : &eline))
867 : {
868 0 : GNUNET_break_op (0);
869 0 : return GNUNET_SYSERR;
870 : }
871 0 : denom_sig->cipher = string_to_cipher (cipher);
872 0 : switch (denom_sig->cipher)
873 : {
874 0 : case TALER_DENOMINATION_RSA:
875 : {
876 : struct GNUNET_JSON_Specification ispec[] = {
877 0 : GNUNET_JSON_spec_rsa_signature (
878 : "blinded_rsa_signature",
879 : &denom_sig->details.blinded_rsa_signature),
880 0 : GNUNET_JSON_spec_end ()
881 : };
882 :
883 0 : if (GNUNET_OK !=
884 0 : GNUNET_JSON_parse (root,
885 : ispec,
886 : &emsg,
887 : &eline))
888 : {
889 0 : GNUNET_break_op (0);
890 0 : return GNUNET_SYSERR;
891 : }
892 0 : return GNUNET_OK;
893 : }
894 0 : case TALER_DENOMINATION_CS:
895 : {
896 : struct GNUNET_JSON_Specification ispec[] = {
897 0 : GNUNET_JSON_spec_uint32 ("b",
898 0 : &denom_sig->details.blinded_cs_answer.b),
899 0 : GNUNET_JSON_spec_fixed_auto ("s",
900 : &denom_sig->details.blinded_cs_answer.
901 : s_scalar),
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 : return GNUNET_SYSERR;
913 : }
914 0 : return GNUNET_OK;
915 : }
916 : break;
917 0 : default:
918 0 : GNUNET_break_op (0);
919 0 : return GNUNET_SYSERR;
920 : }
921 : }
922 :
923 :
924 : /**
925 : * Cleanup data left from parsing denomination public key.
926 : *
927 : * @param cls closure, NULL
928 : * @param[out] spec where to free the data
929 : */
930 : static void
931 0 : clean_blinded_denom_sig (void *cls,
932 : struct GNUNET_JSON_Specification *spec)
933 : {
934 0 : struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
935 :
936 : (void) cls;
937 0 : TALER_blinded_denom_sig_free (denom_sig);
938 0 : }
939 :
940 :
941 : struct GNUNET_JSON_Specification
942 0 : TALER_JSON_spec_blinded_denom_sig (
943 : const char *field,
944 : struct TALER_BlindedDenominationSignature *sig)
945 : {
946 0 : struct GNUNET_JSON_Specification ret = {
947 : .parser = &parse_blinded_denom_sig,
948 : .cleaner = &clean_blinded_denom_sig,
949 : .field = field,
950 : .ptr = sig
951 : };
952 :
953 0 : sig->cipher = TALER_DENOMINATION_INVALID;
954 0 : return ret;
955 : }
956 :
957 :
958 : /**
959 : * Parse given JSON object to blinded planchet.
960 : *
961 : * @param cls closure, NULL
962 : * @param root the json object representing data
963 : * @param[out] spec where to write the data
964 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
965 : */
966 : static enum GNUNET_GenericReturnValue
967 0 : parse_blinded_planchet (void *cls,
968 : json_t *root,
969 : struct GNUNET_JSON_Specification *spec)
970 : {
971 0 : struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
972 : const char *cipher;
973 : struct GNUNET_JSON_Specification dspec[] = {
974 0 : GNUNET_JSON_spec_string ("cipher",
975 : &cipher),
976 0 : GNUNET_JSON_spec_end ()
977 : };
978 : const char *emsg;
979 : unsigned int eline;
980 :
981 : (void) cls;
982 0 : if (GNUNET_OK !=
983 0 : GNUNET_JSON_parse (root,
984 : dspec,
985 : &emsg,
986 : &eline))
987 : {
988 0 : GNUNET_break_op (0);
989 0 : return GNUNET_SYSERR;
990 : }
991 0 : blinded_planchet->cipher = string_to_cipher (cipher);
992 0 : switch (blinded_planchet->cipher)
993 : {
994 0 : case TALER_DENOMINATION_RSA:
995 : {
996 : struct GNUNET_JSON_Specification ispec[] = {
997 0 : GNUNET_JSON_spec_varsize (
998 : "rsa_blinded_planchet",
999 : &blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
1000 : &blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size),
1001 0 : GNUNET_JSON_spec_end ()
1002 : };
1003 :
1004 0 : if (GNUNET_OK !=
1005 0 : GNUNET_JSON_parse (root,
1006 : ispec,
1007 : &emsg,
1008 : &eline))
1009 : {
1010 0 : GNUNET_break_op (0);
1011 0 : return GNUNET_SYSERR;
1012 : }
1013 0 : return GNUNET_OK;
1014 : }
1015 0 : case TALER_DENOMINATION_CS:
1016 : {
1017 : struct GNUNET_JSON_Specification ispec[] = {
1018 0 : GNUNET_JSON_spec_fixed_auto (
1019 : "cs_nonce",
1020 : &blinded_planchet->details.cs_blinded_planchet.nonce),
1021 0 : GNUNET_JSON_spec_fixed_auto (
1022 : "cs_blinded_c0",
1023 : &blinded_planchet->details.cs_blinded_planchet.c[0]),
1024 0 : GNUNET_JSON_spec_fixed_auto (
1025 : "cs_blinded_c1",
1026 : &blinded_planchet->details.cs_blinded_planchet.c[1]),
1027 0 : GNUNET_JSON_spec_end ()
1028 : };
1029 :
1030 0 : if (GNUNET_OK !=
1031 0 : GNUNET_JSON_parse (root,
1032 : ispec,
1033 : &emsg,
1034 : &eline))
1035 : {
1036 0 : GNUNET_break_op (0);
1037 0 : return GNUNET_SYSERR;
1038 : }
1039 0 : return GNUNET_OK;
1040 : }
1041 : break;
1042 0 : default:
1043 0 : GNUNET_break_op (0);
1044 0 : return GNUNET_SYSERR;
1045 : }
1046 : }
1047 :
1048 :
1049 : /**
1050 : * Cleanup data left from parsing blinded planchet.
1051 : *
1052 : * @param cls closure, NULL
1053 : * @param[out] spec where to free the data
1054 : */
1055 : static void
1056 0 : clean_blinded_planchet (void *cls,
1057 : struct GNUNET_JSON_Specification *spec)
1058 : {
1059 0 : struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
1060 :
1061 : (void) cls;
1062 0 : TALER_blinded_planchet_free (blinded_planchet);
1063 0 : }
1064 :
1065 :
1066 : struct GNUNET_JSON_Specification
1067 0 : TALER_JSON_spec_blinded_planchet (const char *field,
1068 : struct TALER_BlindedPlanchet *blinded_planchet)
1069 : {
1070 0 : struct GNUNET_JSON_Specification ret = {
1071 : .parser = &parse_blinded_planchet,
1072 : .cleaner = &clean_blinded_planchet,
1073 : .field = field,
1074 : .ptr = blinded_planchet
1075 : };
1076 :
1077 0 : blinded_planchet->cipher = TALER_DENOMINATION_INVALID;
1078 0 : return ret;
1079 : }
1080 :
1081 :
1082 : /**
1083 : * Parse given JSON object to exchange withdraw values (/csr).
1084 : *
1085 : * @param cls closure, NULL
1086 : * @param root the json object representing data
1087 : * @param[out] spec where to write the data
1088 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1089 : */
1090 : static enum GNUNET_GenericReturnValue
1091 0 : parse_exchange_withdraw_values (void *cls,
1092 : json_t *root,
1093 : struct GNUNET_JSON_Specification *spec)
1094 : {
1095 0 : struct TALER_ExchangeWithdrawValues *ewv = spec->ptr;
1096 : const char *cipher;
1097 : struct GNUNET_JSON_Specification dspec[] = {
1098 0 : GNUNET_JSON_spec_string ("cipher",
1099 : &cipher),
1100 0 : GNUNET_JSON_spec_end ()
1101 : };
1102 : const char *emsg;
1103 : unsigned int eline;
1104 :
1105 : (void) cls;
1106 0 : if (GNUNET_OK !=
1107 0 : GNUNET_JSON_parse (root,
1108 : dspec,
1109 : &emsg,
1110 : &eline))
1111 : {
1112 0 : GNUNET_break_op (0);
1113 0 : return GNUNET_SYSERR;
1114 : }
1115 0 : ewv->cipher = string_to_cipher (cipher);
1116 0 : switch (ewv->cipher)
1117 : {
1118 0 : case TALER_DENOMINATION_RSA:
1119 0 : return GNUNET_OK;
1120 0 : case TALER_DENOMINATION_CS:
1121 : {
1122 : struct GNUNET_JSON_Specification ispec[] = {
1123 0 : GNUNET_JSON_spec_fixed (
1124 : "r_pub_0",
1125 0 : &ewv->details.cs_values.r_pub[0],
1126 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1127 0 : GNUNET_JSON_spec_fixed (
1128 : "r_pub_1",
1129 0 : &ewv->details.cs_values.r_pub[1],
1130 : sizeof (struct GNUNET_CRYPTO_CsRPublic)),
1131 0 : GNUNET_JSON_spec_end ()
1132 : };
1133 :
1134 0 : if (GNUNET_OK !=
1135 0 : GNUNET_JSON_parse (root,
1136 : ispec,
1137 : &emsg,
1138 : &eline))
1139 : {
1140 0 : GNUNET_break_op (0);
1141 0 : return GNUNET_SYSERR;
1142 : }
1143 0 : return GNUNET_OK;
1144 : }
1145 0 : default:
1146 0 : GNUNET_break_op (0);
1147 0 : return GNUNET_SYSERR;
1148 : }
1149 : }
1150 :
1151 :
1152 : struct GNUNET_JSON_Specification
1153 0 : TALER_JSON_spec_exchange_withdraw_values (
1154 : const char *field,
1155 : struct TALER_ExchangeWithdrawValues *ewv)
1156 : {
1157 0 : struct GNUNET_JSON_Specification ret = {
1158 : .parser = &parse_exchange_withdraw_values,
1159 : .field = field,
1160 : .ptr = ewv
1161 : };
1162 :
1163 0 : ewv->cipher = TALER_DENOMINATION_INVALID;
1164 0 : return ret;
1165 : }
1166 :
1167 :
1168 : /**
1169 : * Closure for #parse_i18n_string.
1170 : */
1171 : struct I18nContext
1172 : {
1173 : /**
1174 : * Language pattern to match.
1175 : */
1176 : char *lp;
1177 :
1178 : /**
1179 : * Name of the field to match.
1180 : */
1181 : const char *field;
1182 : };
1183 :
1184 :
1185 : /**
1186 : * Parse given JSON object to internationalized string.
1187 : *
1188 : * @param cls closure, our `struct I18nContext *`
1189 : * @param root the json object representing data
1190 : * @param[out] spec where to write the data
1191 : * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1192 : */
1193 : static enum GNUNET_GenericReturnValue
1194 0 : parse_i18n_string (void *cls,
1195 : json_t *root,
1196 : struct GNUNET_JSON_Specification *spec)
1197 : {
1198 0 : struct I18nContext *ctx = cls;
1199 : json_t *i18n;
1200 : json_t *val;
1201 :
1202 : {
1203 : char *i18nf;
1204 :
1205 0 : GNUNET_asprintf (&i18nf,
1206 : "%s_i18n",
1207 : ctx->field);
1208 0 : i18n = json_object_get (root,
1209 : i18nf);
1210 0 : GNUNET_free (i18nf);
1211 : }
1212 :
1213 0 : val = json_object_get (root,
1214 : ctx->field);
1215 0 : if ( (NULL != i18n) &&
1216 0 : (NULL != ctx->lp) )
1217 : {
1218 0 : double best = 0.0;
1219 : json_t *pos;
1220 : const char *lang;
1221 :
1222 0 : json_object_foreach (i18n, lang, pos)
1223 : {
1224 : double score;
1225 :
1226 0 : score = TALER_language_matches (ctx->lp,
1227 : lang);
1228 0 : if (score > best)
1229 : {
1230 0 : best = score;
1231 0 : val = pos;
1232 : }
1233 : }
1234 : }
1235 :
1236 : {
1237 : const char *str;
1238 :
1239 0 : str = json_string_value (val);
1240 0 : if (NULL == str)
1241 : {
1242 0 : GNUNET_break_op (0);
1243 0 : return GNUNET_SYSERR;
1244 : }
1245 0 : *(const char **) spec->ptr = str;
1246 : }
1247 0 : return GNUNET_OK;
1248 : }
1249 :
1250 :
1251 : /**
1252 : * Function called to clean up data from earlier parsing.
1253 : *
1254 : * @param cls closure
1255 : * @param spec our specification entry with data to clean.
1256 : */
1257 : static void
1258 0 : i18n_cleaner (void *cls,
1259 : struct GNUNET_JSON_Specification *spec)
1260 : {
1261 0 : struct I18nContext *ctx = cls;
1262 :
1263 : (void) spec;
1264 0 : GNUNET_free (ctx->lp);
1265 0 : GNUNET_free (ctx);
1266 0 : }
1267 :
1268 :
1269 : struct GNUNET_JSON_Specification
1270 0 : TALER_JSON_spec_i18n_string (const char *name,
1271 : const char *language_pattern,
1272 : const char **strptr)
1273 : {
1274 0 : struct I18nContext *ctx = GNUNET_new (struct I18nContext);
1275 0 : struct GNUNET_JSON_Specification ret = {
1276 : .parser = &parse_i18n_string,
1277 : .cleaner = &i18n_cleaner,
1278 : .cls = ctx,
1279 : .field = NULL, /* we want the main object */
1280 : .ptr = strptr,
1281 : .ptr_size = 0,
1282 : .size_ptr = NULL
1283 : };
1284 :
1285 0 : ctx->lp = (NULL != language_pattern) ? GNUNET_strdup (language_pattern) :
1286 : NULL;
1287 0 : ctx->field = name;
1288 0 : *strptr = NULL;
1289 0 : return ret;
1290 : }
1291 :
1292 :
1293 : struct GNUNET_JSON_Specification
1294 0 : TALER_JSON_spec_i18n_str (const char *name,
1295 : const char **strptr)
1296 : {
1297 0 : const char *lang = getenv ("LANG");
1298 : char *dot;
1299 : char *l;
1300 : struct GNUNET_JSON_Specification ret;
1301 :
1302 0 : if (NULL != lang)
1303 : {
1304 0 : dot = strchr (lang,
1305 : '.');
1306 0 : if (NULL == dot)
1307 0 : l = GNUNET_strdup (lang);
1308 : else
1309 0 : l = GNUNET_strndup (lang,
1310 : dot - lang);
1311 : }
1312 : else
1313 : {
1314 0 : l = NULL;
1315 : }
1316 0 : ret = TALER_JSON_spec_i18n_string (name,
1317 : l,
1318 : strptr);
1319 0 : GNUNET_free (l);
1320 0 : return ret;
1321 : }
1322 :
1323 :
1324 : /* end of json/json_helper.c */
|