LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 324 673 48.1 %
Date: 2025-06-05 21:03:14 Functions: 41 63 65.1 %

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

Generated by: LCOV version 1.16