LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 54.1 % 739 400
Test Date: 2026-04-14 15:39:31 Functions: 69.7 % 66 46

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

Generated by: LCOV version 2.0-1