LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.1 % 753 400
Test Date: 2026-06-14 14:19:22 Functions: 67.6 % 68 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         1019 : string_to_cipher (const char *cipher_s)
      36              : {
      37         1019 :   if ((0 == strcasecmp (cipher_s,
      38          542 :                         "RSA")) ||
      39          542 :       (0 == strcasecmp (cipher_s,
      40              :                         "RSA+age_restricted")))
      41          552 :     return GNUNET_CRYPTO_BSA_RSA;
      42          467 :   if ((0 == strcasecmp (cipher_s,
      43           70 :                         "CS")) ||
      44           70 :       (0 == strcasecmp (cipher_s,
      45              :                         "CS+age_restricted")))
      46          467 :     return GNUNET_CRYPTO_BSA_CS;
      47            0 :   return GNUNET_CRYPTO_BSA_INVALID;
      48              : }
      49              : 
      50              : 
      51              : json_t *
      52         4751 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
      53              : {
      54         4751 :   char *amount_str = TALER_amount_to_string (amount);
      55              : 
      56         4751 :   GNUNET_assert (NULL != amount_str);
      57              :   {
      58         4751 :     json_t *j = json_string (amount_str);
      59              : 
      60         4751 :     GNUNET_free (amount_str);
      61         4751 :     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         7073 : parse_amount (void *cls,
      76              :               json_t *root,
      77              :               struct GNUNET_JSON_Specification *spec)
      78              : {
      79         7073 :   const char *currency = cls;
      80         7073 :   struct TALER_Amount *r_amount = spec->ptr;
      81              : 
      82              :   (void) cls;
      83         7073 :   if (! json_is_string (root))
      84              :   {
      85            0 :     GNUNET_break_op (0);
      86            0 :     return GNUNET_SYSERR;
      87              :   }
      88         7073 :   if (GNUNET_OK !=
      89         7073 :       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         7073 :   if ( (NULL != currency) &&
      96              :        (0 !=
      97         4962 :         strcasecmp (currency,
      98         4962 :                     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         7073 :   return GNUNET_OK;
     109              : }
     110              : 
     111              : 
     112              : struct GNUNET_JSON_Specification
     113         4993 : TALER_JSON_spec_amount (const char *name,
     114              :                         const char *currency,
     115              :                         struct TALER_Amount *r_amount)
     116              : {
     117         4993 :   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         4993 :   GNUNET_assert (NULL != currency);
     128         4993 :   return ret;
     129              : }
     130              : 
     131              : 
     132              : struct GNUNET_JSON_Specification
     133         2219 : TALER_JSON_spec_amount_any (const char *name,
     134              :                             struct TALER_Amount *r_amount)
     135              : {
     136         2219 :   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         2219 :   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          710 : parse_denom_pub (void *cls,
     731              :                  json_t *root,
     732              :                  struct GNUNET_JSON_Specification *spec)
     733              : {
     734          710 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     735              :   struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
     736              :   const char *cipher;
     737          710 :   bool age_mask_missing = false;
     738              :   struct GNUNET_JSON_Specification dspec[] = {
     739          710 :     GNUNET_JSON_spec_string ("cipher",
     740              :                              &cipher),
     741          710 :     GNUNET_JSON_spec_mark_optional (
     742              :       GNUNET_JSON_spec_uint32 ("age_mask",
     743              :                                &denom_pub->age_mask.bits),
     744              :       &age_mask_missing),
     745          710 :     GNUNET_JSON_spec_end ()
     746              :   };
     747              :   const char *emsg;
     748              :   unsigned int eline;
     749              : 
     750              :   (void) cls;
     751          710 :   if (GNUNET_OK !=
     752          710 :       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          710 :   if (age_mask_missing)
     762            0 :     denom_pub->age_mask.bits = 0;
     763          710 :   bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     764          710 :   bsign_pub->rc = 1;
     765          710 :   bsign_pub->cipher = string_to_cipher (cipher);
     766          710 :   switch (bsign_pub->cipher)
     767              :   {
     768            0 :   case GNUNET_CRYPTO_BSA_INVALID:
     769            0 :     break;
     770          392 :   case GNUNET_CRYPTO_BSA_RSA:
     771              :     {
     772              :       struct GNUNET_JSON_Specification ispec[] = {
     773          392 :         GNUNET_JSON_spec_rsa_public_key (
     774              :           "rsa_pub",
     775              :           &bsign_pub->details.rsa_public_key),
     776          392 :         GNUNET_JSON_spec_end ()
     777              :       };
     778              : 
     779          392 :       if (GNUNET_OK !=
     780          392 :           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          392 :       denom_pub->bsign_pub_key = bsign_pub;
     790          392 :       return GNUNET_OK;
     791              :     }
     792          318 :   case GNUNET_CRYPTO_BSA_CS:
     793              :     {
     794              :       struct GNUNET_JSON_Specification ispec[] = {
     795          318 :         GNUNET_JSON_spec_fixed ("cs_pub",
     796          318 :                                 &bsign_pub->details.cs_public_key,
     797              :                                 sizeof (bsign_pub->details.cs_public_key)),
     798          318 :         GNUNET_JSON_spec_end ()
     799              :       };
     800              : 
     801          318 :       if (GNUNET_OK !=
     802          318 :           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          318 :       denom_pub->bsign_pub_key = bsign_pub;
     812          318 :       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          535 : clean_denom_pub (void *cls,
     829              :                  struct GNUNET_JSON_Specification *spec)
     830              : {
     831          535 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     832              : 
     833              :   (void) cls;
     834          535 :   TALER_denom_pub_free (denom_pub);
     835          535 : }
     836              : 
     837              : 
     838              : struct GNUNET_JSON_Specification
     839          710 : TALER_JSON_spec_denom_pub (const char *field,
     840              :                            struct TALER_DenominationPublicKey *pk)
     841              : {
     842          710 :   struct GNUNET_JSON_Specification ret = {
     843              :     .parser = &parse_denom_pub,
     844              :     .cleaner = &clean_denom_pub,
     845              :     .field = field,
     846              :     .ptr = pk
     847              :   };
     848              : 
     849          710 :   pk->bsign_pub_key = NULL;
     850          710 :   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          896 : parse_denom_pub_cipher (void *cls,
     997              :                         json_t *root,
     998              :                         struct GNUNET_JSON_Specification *spec)
     999              : {
    1000          896 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
    1001          896 :   enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher =
    1002          896 :     (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls;
    1003              :   struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
    1004              :   const char *emsg;
    1005              :   unsigned int eline;
    1006              : 
    1007          896 :   bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
    1008          896 :   bsign_pub->cipher = cipher;
    1009          896 :   bsign_pub->rc = 1;
    1010          896 :   switch (cipher)
    1011              :   {
    1012            0 :   case GNUNET_CRYPTO_BSA_INVALID:
    1013            0 :     break;
    1014          466 :   case GNUNET_CRYPTO_BSA_RSA:
    1015              :     {
    1016              :       struct GNUNET_JSON_Specification ispec[] = {
    1017          466 :         GNUNET_JSON_spec_rsa_public_key (
    1018              :           "rsa_pub",
    1019              :           &bsign_pub->details.rsa_public_key),
    1020          466 :         GNUNET_JSON_spec_end ()
    1021              :       };
    1022              : 
    1023          466 :       if (GNUNET_OK !=
    1024          466 :           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          466 :       denom_pub->bsign_pub_key = bsign_pub;
    1034          466 :       return GNUNET_OK;
    1035              :     }
    1036          430 :   case GNUNET_CRYPTO_BSA_CS:
    1037              :     {
    1038              :       struct GNUNET_JSON_Specification ispec[] = {
    1039          430 :         GNUNET_JSON_spec_fixed ("cs_pub",
    1040          430 :                                 &bsign_pub->details.cs_public_key,
    1041              :                                 sizeof (bsign_pub->details.cs_public_key)),
    1042          430 :         GNUNET_JSON_spec_end ()
    1043              :       };
    1044              : 
    1045          430 :       if (GNUNET_OK !=
    1046          430 :           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          430 :       denom_pub->bsign_pub_key = bsign_pub;
    1056          430 :       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          896 : TALER_JSON_spec_denom_pub_cipher (
    1067              :   const char *field,
    1068              :   enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
    1069              :   struct TALER_DenominationPublicKey *pk)
    1070              : {
    1071          896 :   struct GNUNET_JSON_Specification ret = {
    1072              :     .parser = &parse_denom_pub_cipher,
    1073              :     .cleaner = &clean_denom_pub,
    1074              :     .field = field,
    1075          896 :     .cls = (void *) cipher,
    1076              :     .ptr = pk
    1077              :   };
    1078              : 
    1079          896 :   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 slug.
    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            0 : parse_slug (void *cls,
    1490              :             json_t *root,
    1491              :             struct GNUNET_JSON_Specification *spec)
    1492              : {
    1493              :   const char *str;
    1494              : 
    1495              :   (void) cls;
    1496            0 :   str = json_string_value (root);
    1497            0 :   if (NULL == str)
    1498              :   {
    1499            0 :     GNUNET_break_op (0);
    1500            0 :     return GNUNET_SYSERR;
    1501              :   }
    1502            0 :   if (! TALER_is_slug (str))
    1503              :   {
    1504            0 :     GNUNET_break_op (0);
    1505            0 :     return GNUNET_SYSERR;
    1506              :   }
    1507            0 :   *(const char **) spec->ptr = str;
    1508            0 :   return GNUNET_OK;
    1509              : }
    1510              : 
    1511              : 
    1512              : struct GNUNET_JSON_Specification
    1513            0 : TALER_JSON_spec_slug (const char *field,
    1514              :                       const char **slug)
    1515              : {
    1516            0 :   struct GNUNET_JSON_Specification ret = {
    1517              :     .parser = &parse_slug,
    1518              :     .field = field,
    1519              :     .ptr = slug
    1520              :   };
    1521              : 
    1522            0 :   *slug = NULL;
    1523            0 :   return ret;
    1524              : }
    1525              : 
    1526              : 
    1527              : /**
    1528              :  * Parse given JSON object to payto:// URI.
    1529              :  *
    1530              :  * @param cls closure, NULL
    1531              :  * @param root the json object representing data
    1532              :  * @param[out] spec where to write the data
    1533              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1534              :  */
    1535              : static enum GNUNET_GenericReturnValue
    1536          764 : parse_full_payto_uri (void *cls,
    1537              :                       json_t *root,
    1538              :                       struct GNUNET_JSON_Specification *spec)
    1539              : {
    1540          764 :   struct TALER_FullPayto *payto_uri = spec->ptr;
    1541              :   const char *str;
    1542              :   char *err;
    1543              : 
    1544              :   (void) cls;
    1545          764 :   str = json_string_value (root);
    1546          764 :   if (NULL == str)
    1547              :   {
    1548            0 :     GNUNET_break_op (0);
    1549            0 :     return GNUNET_SYSERR;
    1550              :   }
    1551          764 :   payto_uri->full_payto = (char *) str;
    1552          764 :   err = TALER_payto_validate (*payto_uri);
    1553          764 :   if (NULL != err)
    1554              :   {
    1555            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1556              :                 "payto:// malformed: %s\n",
    1557              :                 err);
    1558            0 :     GNUNET_free (err);
    1559            0 :     payto_uri->full_payto = NULL;
    1560            0 :     return GNUNET_SYSERR;
    1561              :   }
    1562          764 :   return GNUNET_OK;
    1563              : }
    1564              : 
    1565              : 
    1566              : struct GNUNET_JSON_Specification
    1567          766 : TALER_JSON_spec_full_payto_uri (
    1568              :   const char *field,
    1569              :   struct TALER_FullPayto *payto_uri)
    1570              : {
    1571          766 :   struct GNUNET_JSON_Specification ret = {
    1572              :     .parser = &parse_full_payto_uri,
    1573              :     .field = field,
    1574              :     .ptr = payto_uri
    1575              :   };
    1576              : 
    1577          766 :   payto_uri->full_payto = NULL;
    1578          766 :   return ret;
    1579              : }
    1580              : 
    1581              : 
    1582              : /**
    1583              :  * Parse given JSON object to payto:// URI.
    1584              :  *
    1585              :  * @param cls closure, NULL
    1586              :  * @param root the json object representing data
    1587              :  * @param[out] spec where to write the data
    1588              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1589              :  */
    1590              : static enum GNUNET_GenericReturnValue
    1591            6 : parse_normalized_payto_uri (void *cls,
    1592              :                             json_t *root,
    1593              :                             struct GNUNET_JSON_Specification *spec)
    1594              : {
    1595            6 :   struct TALER_NormalizedPayto *payto_uri = spec->ptr;
    1596              :   const char *str;
    1597              : 
    1598              :   (void) cls;
    1599            6 :   str = json_string_value (root);
    1600            6 :   if (NULL == str)
    1601              :   {
    1602            0 :     GNUNET_break_op (0);
    1603            0 :     return GNUNET_SYSERR;
    1604              :   }
    1605            6 :   payto_uri->normalized_payto = (char *) str;
    1606              :   {
    1607              :     char *err;
    1608              : 
    1609            6 :     err = TALER_normalized_payto_validate (*payto_uri);
    1610            6 :     if (NULL != err)
    1611              :     {
    1612            0 :       GNUNET_break_op (0);
    1613            0 :       GNUNET_free (err);
    1614            0 :       payto_uri->normalized_payto = NULL;
    1615            0 :       return GNUNET_SYSERR;
    1616              :     }
    1617              :   }
    1618            6 :   return GNUNET_OK;
    1619              : }
    1620              : 
    1621              : 
    1622              : struct GNUNET_JSON_Specification
    1623            6 : TALER_JSON_spec_normalized_payto_uri (
    1624              :   const char *field,
    1625              :   struct TALER_NormalizedPayto *payto_uri)
    1626              : {
    1627            6 :   struct GNUNET_JSON_Specification ret = {
    1628              :     .parser = &parse_normalized_payto_uri,
    1629              :     .field = field,
    1630              :     .ptr = payto_uri
    1631              :   };
    1632              : 
    1633            6 :   payto_uri->normalized_payto = NULL;
    1634            6 :   return ret;
    1635              : }
    1636              : 
    1637              : 
    1638              : /**
    1639              :  * Parse given JSON object with protocol version.
    1640              :  *
    1641              :  * @param cls closure, NULL
    1642              :  * @param root the json object representing data
    1643              :  * @param[out] spec where to write the data
    1644              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1645              :  */
    1646              : static enum GNUNET_GenericReturnValue
    1647           47 : parse_protocol_version (void *cls,
    1648              :                         json_t *root,
    1649              :                         struct GNUNET_JSON_Specification *spec)
    1650              : {
    1651           47 :   struct TALER_JSON_ProtocolVersion *pv = spec->ptr;
    1652              :   const char *ver;
    1653              :   char dummy;
    1654              : 
    1655              :   (void) cls;
    1656           47 :   if (! json_is_string (root))
    1657              :   {
    1658            0 :     GNUNET_break_op (0);
    1659            0 :     return GNUNET_SYSERR;
    1660              :   }
    1661           47 :   ver = json_string_value (root);
    1662           47 :   if (3 != sscanf (ver,
    1663              :                    "%u:%u:%u%c",
    1664              :                    &pv->current,
    1665              :                    &pv->revision,
    1666              :                    &pv->age,
    1667              :                    &dummy))
    1668              :   {
    1669            0 :     GNUNET_break_op (0);
    1670            0 :     return GNUNET_SYSERR;
    1671              :   }
    1672           47 :   return GNUNET_OK;
    1673              : }
    1674              : 
    1675              : 
    1676              : struct GNUNET_JSON_Specification
    1677           47 : TALER_JSON_spec_version (const char *field,
    1678              :                          struct TALER_JSON_ProtocolVersion *ver)
    1679              : {
    1680           47 :   struct GNUNET_JSON_Specification ret = {
    1681              :     .parser = &parse_protocol_version,
    1682              :     .field = field,
    1683              :     .ptr = ver
    1684              :   };
    1685              : 
    1686           47 :   return ret;
    1687              : }
    1688              : 
    1689              : 
    1690              : /**
    1691              :  * Parse given JSON object to an OTP key.
    1692              :  *
    1693              :  * @param cls closure, NULL
    1694              :  * @param root the json object representing data
    1695              :  * @param[out] spec where to write the data
    1696              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1697              :  */
    1698              : static enum GNUNET_GenericReturnValue
    1699            0 : parse_otp_key (void *cls,
    1700              :                json_t *root,
    1701              :                struct GNUNET_JSON_Specification *spec)
    1702              : {
    1703              :   const char *pos_key;
    1704              : 
    1705              :   (void) cls;
    1706            0 :   pos_key = json_string_value (root);
    1707            0 :   if (NULL == pos_key)
    1708              :   {
    1709            0 :     GNUNET_break_op (0);
    1710            0 :     return GNUNET_SYSERR;
    1711              :   }
    1712              :   {
    1713            0 :     size_t pos_key_length = strlen (pos_key);
    1714              :     void *key; /* pos_key in binary */
    1715              :     size_t key_len; /* length of the key */
    1716              :     int dret;
    1717              : 
    1718            0 :     key_len = pos_key_length * 5 / 8;
    1719            0 :     key = GNUNET_malloc (key_len);
    1720            0 :     dret = TALER_rfc3548_base32decode (pos_key,
    1721              :                                        pos_key_length,
    1722              :                                        key,
    1723              :                                        key_len);
    1724            0 :     if (-1 == dret)
    1725              :     {
    1726            0 :       GNUNET_free (key);
    1727            0 :       GNUNET_break_op (0);
    1728            0 :       return GNUNET_SYSERR;
    1729              :     }
    1730            0 :     GNUNET_free (key);
    1731              :   }
    1732            0 :   *(const char **) spec->ptr = pos_key;
    1733            0 :   return GNUNET_OK;
    1734              : }
    1735              : 
    1736              : 
    1737              : struct GNUNET_JSON_Specification
    1738            0 : TALER_JSON_spec_otp_key (const char *name,
    1739              :                          const char **otp_key)
    1740              : {
    1741            0 :   struct GNUNET_JSON_Specification ret = {
    1742              :     .parser = &parse_otp_key,
    1743              :     .field = name,
    1744              :     .ptr = otp_key
    1745              :   };
    1746              : 
    1747            0 :   *otp_key = NULL;
    1748            0 :   return ret;
    1749              : }
    1750              : 
    1751              : 
    1752              : /**
    1753              :  * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm`
    1754              :  *
    1755              :  * @param cls closure, NULL
    1756              :  * @param root the json object representing data
    1757              :  * @param[out] spec where to write the data
    1758              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1759              :  */
    1760              : static enum GNUNET_GenericReturnValue
    1761            0 : parse_otp_type (void *cls,
    1762              :                 json_t *root,
    1763              :                 struct GNUNET_JSON_Specification *spec)
    1764              : {
    1765              :   static const struct Entry
    1766              :   {
    1767              :     const char *name;
    1768              :     enum TALER_MerchantConfirmationAlgorithm val;
    1769              :   } lt [] = {
    1770              :     { .name = "NONE",
    1771              :       .val = TALER_MCA_NONE },
    1772              :     { .name = "TOTP_WITHOUT_PRICE",
    1773              :       .val = TALER_MCA_WITHOUT_PRICE },
    1774              :     { .name = "TOTP_WITH_PRICE",
    1775              :       .val = TALER_MCA_WITH_PRICE },
    1776              :     { .name = NULL,
    1777              :       .val = TALER_MCA_NONE },
    1778              :   };
    1779            0 :   enum TALER_MerchantConfirmationAlgorithm *res
    1780              :     = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr;
    1781              : 
    1782              :   (void) cls;
    1783            0 :   if (json_is_string (root))
    1784              :   {
    1785              :     const char *str;
    1786              : 
    1787            0 :     str = json_string_value (root);
    1788            0 :     if (NULL == str)
    1789              :     {
    1790            0 :       GNUNET_break_op (0);
    1791            0 :       return GNUNET_SYSERR;
    1792              :     }
    1793            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    1794              :     {
    1795            0 :       if (0 == strcasecmp (str,
    1796            0 :                            lt[i].name))
    1797              :       {
    1798            0 :         *res = lt[i].val;
    1799            0 :         return GNUNET_OK;
    1800              :       }
    1801              :     }
    1802            0 :     GNUNET_break_op (0);
    1803              :   }
    1804            0 :   if (json_is_integer (root))
    1805              :   {
    1806              :     json_int_t val;
    1807              : 
    1808            0 :     val = json_integer_value (root);
    1809            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    1810              :     {
    1811            0 :       if (val == lt[i].val)
    1812              :       {
    1813            0 :         *res = lt[i].val;
    1814            0 :         return GNUNET_OK;
    1815              :       }
    1816              :     }
    1817            0 :     GNUNET_break_op (0);
    1818            0 :     return GNUNET_SYSERR;
    1819              :   }
    1820            0 :   GNUNET_break_op (0);
    1821            0 :   return GNUNET_SYSERR;
    1822              : }
    1823              : 
    1824              : 
    1825              : struct GNUNET_JSON_Specification
    1826            0 : TALER_JSON_spec_otp_type (const char *name,
    1827              :                           enum TALER_MerchantConfirmationAlgorithm *mca)
    1828              : {
    1829            0 :   struct GNUNET_JSON_Specification ret = {
    1830              :     .parser = &parse_otp_type,
    1831              :     .field = name,
    1832              :     .ptr = mca
    1833              :   };
    1834              : 
    1835            0 :   *mca = TALER_MCA_NONE;
    1836            0 :   return ret;
    1837              : }
    1838              : 
    1839              : 
    1840              : /**
    1841              :  * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent`
    1842              :  *
    1843              :  * @param cls closure, NULL
    1844              :  * @param root the json object representing data
    1845              :  * @param[out] spec where to write the data
    1846              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1847              :  */
    1848              : static enum GNUNET_GenericReturnValue
    1849          334 : parse_kycte (void *cls,
    1850              :              json_t *root,
    1851              :              struct GNUNET_JSON_Specification *spec)
    1852              : {
    1853              :   static const struct Entry
    1854              :   {
    1855              :     const char *name;
    1856              :     enum TALER_KYCLOGIC_KycTriggerEvent val;
    1857              :   } lt [] = {
    1858              :     { .name = "NONE",
    1859              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
    1860              :     { .name = "WITHDRAW",
    1861              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
    1862              :     { .name = "DEPOSIT",
    1863              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
    1864              :     { .name = "MERGE",
    1865              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
    1866              :     { .name = "BALANCE",
    1867              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
    1868              :     { .name = "CLOSE",
    1869              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
    1870              :     { .name = "AGGREGATE",
    1871              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
    1872              :     { .name = "TRANSACTION",
    1873              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
    1874              :     { .name = "REFUND",
    1875              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
    1876              :     { .name = NULL,
    1877              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
    1878              :   };
    1879          334 :   enum TALER_KYCLOGIC_KycTriggerEvent *res
    1880              :     = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr;
    1881              : 
    1882              :   (void) cls;
    1883          334 :   if (json_is_string (root))
    1884              :   {
    1885              :     const char *str;
    1886              : 
    1887          334 :     str = json_string_value (root);
    1888          334 :     if (NULL == str)
    1889              :     {
    1890            0 :       GNUNET_break_op (0);
    1891            0 :       return GNUNET_SYSERR;
    1892              :     }
    1893         1545 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    1894              :     {
    1895         1545 :       if (0 == strcasecmp (str,
    1896         1545 :                            lt[i].name))
    1897              :       {
    1898          334 :         *res = lt[i].val;
    1899          334 :         return GNUNET_OK;
    1900              :       }
    1901              :     }
    1902            0 :     GNUNET_break_op (0);
    1903            0 :     return GNUNET_SYSERR;
    1904              :   }
    1905            0 :   if (json_is_integer (root))
    1906              :   {
    1907              :     json_int_t val;
    1908              : 
    1909            0 :     val = json_integer_value (root);
    1910            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    1911              :     {
    1912            0 :       if (val == lt[i].val)
    1913              :       {
    1914            0 :         *res = lt[i].val;
    1915            0 :         return GNUNET_OK;
    1916              :       }
    1917              :     }
    1918            0 :     GNUNET_break_op (0);
    1919            0 :     return GNUNET_SYSERR;
    1920              :   }
    1921            0 :   GNUNET_break_op (0);
    1922            0 :   return GNUNET_SYSERR;
    1923              : }
    1924              : 
    1925              : 
    1926              : struct GNUNET_JSON_Specification
    1927          335 : TALER_JSON_spec_kycte (const char *name,
    1928              :                        enum TALER_KYCLOGIC_KycTriggerEvent *kte)
    1929              : {
    1930          335 :   struct GNUNET_JSON_Specification ret = {
    1931              :     .parser = &parse_kycte,
    1932              :     .field = name,
    1933              :     .ptr = kte
    1934              :   };
    1935              : 
    1936          335 :   *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE;
    1937          335 :   return ret;
    1938              : }
    1939              : 
    1940              : 
    1941              : /**
    1942              :  * Parser combinator of a tuple of parsers, for parsing
    1943              :  * an array of expected size and element types.
    1944              :  *
    1945              :  * @param cls closure, array of specs, NULL terminated
    1946              :  * @param root the json root
    1947              :  * @param[out] spec where to write the data
    1948              :  */
    1949              : static enum GNUNET_GenericReturnValue
    1950          115 : parse_tuple_of (void *cls,
    1951              :                 json_t *root,
    1952              :                 struct GNUNET_JSON_Specification *spec)
    1953              : {
    1954          115 :   struct GNUNET_JSON_Specification *specs = cls;
    1955              :   static size_t max_specs = 100;
    1956          115 :   bool found_end = false;
    1957              : 
    1958              :   enum GNUNET_GenericReturnValue ret;
    1959              : 
    1960          115 :   if (! json_is_array (root))
    1961              :   {
    1962            0 :     return GNUNET_SYSERR;
    1963              :   }
    1964              : 
    1965              :   {
    1966              :     size_t num;
    1967          345 :     for (num = 0; num< max_specs; num++)
    1968              :     {
    1969          345 :       if (NULL == specs[num].parser)
    1970              :       {
    1971          115 :         found_end = true;
    1972          115 :         break;
    1973              :       }
    1974              :     }
    1975          115 :     GNUNET_assert (found_end);
    1976              : 
    1977          115 :     if (num != json_array_size (root))
    1978              :     {
    1979            0 :       GNUNET_break_op (0);
    1980            0 :       return GNUNET_SYSERR;
    1981              :     }
    1982              :   }
    1983              : 
    1984              :   {
    1985              :     json_t *j_entry;
    1986              :     size_t idx;
    1987              : 
    1988          345 :     json_array_foreach (root, idx, j_entry) {
    1989          230 :       ret = GNUNET_JSON_parse (j_entry,
    1990          230 :                                &specs[idx],
    1991              :                                NULL,
    1992              :                                NULL);
    1993          230 :       if (GNUNET_OK != ret)
    1994              :       {
    1995            0 :         GNUNET_break_op (0);
    1996            0 :         return GNUNET_SYSERR;
    1997              :       }
    1998              :     }
    1999              :   }
    2000              : 
    2001          115 :   return GNUNET_OK;
    2002              : }
    2003              : 
    2004              : 
    2005              : struct GNUNET_JSON_Specification
    2006          129 : TALER_JSON_spec_tuple_of (
    2007              :   const char *field,
    2008              :   struct GNUNET_JSON_Specification specs[])
    2009              : {
    2010          129 :   struct GNUNET_JSON_Specification ret = {
    2011              :     .parser = &parse_tuple_of,
    2012              :     .field = field,
    2013              :     .cls = specs
    2014              :   };
    2015              : 
    2016          129 :   return ret;
    2017              : }
    2018              : 
    2019              : 
    2020              : /**
    2021              :  * Parser for an array of unknown length but
    2022              :  * of elements of the same type with the same
    2023              :  * fixed length.
    2024              :  *
    2025              :  * @param cls closure, entry_size
    2026              :  * @param root the json root
    2027              :  * @param spec the output spec
    2028              :  */
    2029              : static enum GNUNET_GenericReturnValue
    2030           90 : parse_array_fixed (void *cls,
    2031              :                    json_t *root,
    2032              :                    struct GNUNET_JSON_Specification *spec)
    2033              : {
    2034              :   enum GNUNET_GenericReturnValue ret;
    2035           90 :   size_t entry_size = (size_t) cls;
    2036              :   size_t num_entries;
    2037              : 
    2038           90 :   GNUNET_assert (0< entry_size);
    2039           90 :   num_entries = spec->ptr_size / entry_size;
    2040           90 :   GNUNET_assert (0 < num_entries);
    2041              : 
    2042              : 
    2043           90 :   if (! json_is_array (root))
    2044              :   {
    2045            0 :     GNUNET_break_op (0);
    2046            0 :     return GNUNET_SYSERR;
    2047              :   }
    2048           90 :   if (num_entries != json_array_size (root))
    2049              :   {
    2050            0 :     GNUNET_break_op (0);
    2051            0 :     return GNUNET_SYSERR;
    2052              :   }
    2053              : 
    2054              :   {
    2055              :     json_t *j_entry;
    2056              :     size_t idx;
    2057           90 :     void *ptr = spec->ptr;
    2058           90 :     void *end = spec->ptr + spec->ptr_size;
    2059              : 
    2060          450 :     json_array_foreach (root, idx, j_entry) {
    2061              :       struct GNUNET_JSON_Specification esp[] = {
    2062          360 :         GNUNET_JSON_spec_fixed (NULL,
    2063              :                                 ptr,
    2064              :                                 entry_size),
    2065          360 :         GNUNET_JSON_spec_end ()
    2066              :       };
    2067          360 :       GNUNET_assert (ptr < end);
    2068          360 :       ret = GNUNET_JSON_parse (j_entry,
    2069              :                                esp,
    2070              :                                NULL,
    2071              :                                NULL);
    2072          360 :       if (GNUNET_OK != ret)
    2073              :       {
    2074            0 :         GNUNET_break_op (0);
    2075            0 :         return GNUNET_SYSERR;
    2076              :       }
    2077          360 :       ptr += entry_size;
    2078              :     }
    2079              :   }
    2080           90 :   return GNUNET_OK;
    2081              : }
    2082              : 
    2083              : 
    2084              : struct GNUNET_JSON_Specification
    2085           90 : TALER_JSON_spec_array_fixed (
    2086              :   const char *field,
    2087              :   size_t num_entries,
    2088              :   void *entries,
    2089              :   size_t entry_size)
    2090              : {
    2091           90 :   struct GNUNET_JSON_Specification ret = {
    2092              :     .parser = &parse_array_fixed,
    2093              :     .ptr = entries,
    2094           90 :     .ptr_size = entry_size * num_entries,
    2095              :     .field = field,
    2096           90 :     .cls = (void *) entry_size,
    2097              :   };
    2098              : 
    2099           90 :   GNUNET_assert ((num_entries <= 1) ||
    2100              :                  (entry_size * num_entries > entry_size));
    2101           90 :   return ret;
    2102              : }
    2103              : 
    2104              : 
    2105              : /**
    2106              :  * Closure for the parser of arrays of fixed size data
    2107              :  * of unknown array length
    2108              :  */
    2109              : struct closure_array_of_data
    2110              : {
    2111              :   /**
    2112              :    * Fixed (known) size per entry
    2113              :    */
    2114              :   size_t entry_size;
    2115              : 
    2116              :   /**
    2117              :    * Pointer where to put the number of elements
    2118              :    * allocated, i.e. the number of elements in the
    2119              :    * json array.
    2120              :    */
    2121              :   size_t *num_entries;
    2122              : };
    2123              : 
    2124              : /**
    2125              :  * Parser for an array of data of known element size,
    2126              :  * but unknown array length
    2127              :  */
    2128              : static enum GNUNET_GenericReturnValue
    2129            8 : parse_array_of_data (void *cls,
    2130              :                      json_t *root,
    2131              :                      struct GNUNET_JSON_Specification *spec)
    2132              : {
    2133              :   enum GNUNET_GenericReturnValue ret;
    2134            8 :   struct closure_array_of_data *info = cls;
    2135              :   size_t num_entries;
    2136              : 
    2137            8 :   if (! json_is_array (root))
    2138              :   {
    2139            0 :     GNUNET_break_op (0);
    2140            0 :     return GNUNET_SYSERR;
    2141              :   }
    2142            8 :   num_entries = json_array_size (root);
    2143            8 :   *info->num_entries = num_entries;
    2144            8 :   if (0 == num_entries)
    2145              :   {
    2146            0 :     *(char **) spec->ptr = NULL;
    2147            0 :     return GNUNET_OK;
    2148              :   }
    2149              : 
    2150            8 :   spec->ptr_size = num_entries * info->entry_size;
    2151            8 :   GNUNET_assert (spec->ptr_size > num_entries);
    2152            8 :   *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size);
    2153              : 
    2154              :   {
    2155              :     json_t *j_entry;
    2156              :     size_t idx;
    2157            8 :     char *ptr = *(char **) spec->ptr;
    2158            8 :     char *end = ptr + spec->ptr_size;
    2159              : 
    2160           25 :     json_array_foreach (root, idx, j_entry) {
    2161              :       struct GNUNET_JSON_Specification esp[] = {
    2162           17 :         GNUNET_JSON_spec_fixed (NULL,
    2163              :                                 ptr,
    2164              :                                 info->entry_size),
    2165           17 :         GNUNET_JSON_spec_end ()
    2166              :       };
    2167           17 :       GNUNET_assert (ptr < end);
    2168           17 :       ret = GNUNET_JSON_parse (j_entry,
    2169              :                                esp,
    2170              :                                NULL,
    2171              :                                NULL);
    2172           17 :       if (GNUNET_OK != ret)
    2173              :       {
    2174            0 :         GNUNET_break_op (0);
    2175            0 :         return GNUNET_SYSERR;
    2176              :       }
    2177           17 :       ptr += info->entry_size;
    2178              :     }
    2179              :   }
    2180            8 :   return GNUNET_OK;
    2181              : }
    2182              : 
    2183              : 
    2184              : /**
    2185              :  * Cleanup data left from parsing an array of fixed size (but unknown length).
    2186              :  *
    2187              :  * @param cls closure_of_array_data
    2188              :  * @param[out] spec where to free the data
    2189              :  */
    2190              : static void
    2191            7 : cleaner_array_of_data (void *cls,
    2192              :                        struct GNUNET_JSON_Specification *spec)
    2193              : {
    2194            7 :   struct closure_array_of_data *info = cls;
    2195              : 
    2196            7 :   GNUNET_free (*(void **) spec->ptr);
    2197            7 :   GNUNET_free (info);
    2198            7 : }
    2199              : 
    2200              : 
    2201              : struct GNUNET_JSON_Specification
    2202            8 : TALER_JSON_spec_array_of_data (
    2203              :   const char *field,
    2204              :   size_t entry_size,
    2205              :   size_t *num_entries,
    2206              :   void **entries)
    2207              : {
    2208              :   struct closure_array_of_data *cls;
    2209              : 
    2210            8 :   GNUNET_assert (0< entry_size);
    2211            8 :   *entries = NULL;
    2212            8 :   *num_entries = 0;
    2213            8 :   cls = GNUNET_new (struct closure_array_of_data);
    2214            8 :   cls->num_entries = num_entries;
    2215            8 :   cls->entry_size = entry_size;
    2216              :   {
    2217            8 :     struct GNUNET_JSON_Specification ret = {
    2218              :       .parser = &parse_array_of_data,
    2219              :       .ptr = entries,
    2220              :       .field = field,
    2221              :       .cleaner = &cleaner_array_of_data,
    2222              :       .cls = (void *) cls,
    2223              :     };
    2224              : 
    2225            8 :     return ret;
    2226              :   }
    2227              : }
    2228              : 
    2229              : 
    2230              : struct GNUNET_JSON_Specification
    2231            7 : TALER_JSON_spec_array_of_denom_pub_h (
    2232              :   const char *field,
    2233              :   size_t *num_entries,
    2234              :   struct TALER_DenominationHashP **entries)
    2235              : {
    2236            7 :   *num_entries = 0;
    2237            7 :   *entries = NULL;
    2238            7 :   return TALER_JSON_spec_array_of_data (
    2239              :     field,
    2240              :     sizeof (struct TALER_DenominationHashP),
    2241              :     num_entries,
    2242              :     (void **) entries);
    2243              : }
    2244              : 
    2245              : 
    2246              : /**
    2247              :  * Parser for an array of blinded denomination signatures,
    2248              :  * of unknown array length
    2249              :  */
    2250              : static enum GNUNET_GenericReturnValue
    2251           14 : parse_array_of_blinded_denom_sigs (void *cls,
    2252              :                                    json_t *root,
    2253              :                                    struct GNUNET_JSON_Specification *spec)
    2254              : {
    2255              :   enum GNUNET_GenericReturnValue ret;
    2256           14 :   struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
    2257           14 :   size_t expected_num_entries = (size_t) cls;
    2258              :   size_t num_entries;
    2259              : 
    2260           14 :   if (! json_is_array (root))
    2261              :   {
    2262            0 :     GNUNET_break_op (0);
    2263            0 :     return GNUNET_SYSERR;
    2264              :   }
    2265           14 :   num_entries = json_array_size (root);
    2266           14 :   if (num_entries != expected_num_entries)
    2267              :   {
    2268            0 :     GNUNET_break_op (0);
    2269            0 :     return GNUNET_SYSERR;
    2270              :   }
    2271              : 
    2272              :   {
    2273              :     json_t *j_entry;
    2274              :     size_t idx;
    2275           14 :     struct TALER_BlindedDenominationSignature *ptr = sigs;
    2276              : 
    2277           70 :     json_array_foreach (root, idx, j_entry) {
    2278              :       struct GNUNET_JSON_Specification esp[] = {
    2279           56 :         TALER_JSON_spec_blinded_denom_sig (NULL,
    2280              :                                            ptr),
    2281           56 :         GNUNET_JSON_spec_end ()
    2282              :       };
    2283           56 :       ret = GNUNET_JSON_parse (j_entry,
    2284              :                                esp,
    2285              :                                NULL,
    2286              :                                NULL);
    2287           56 :       if (GNUNET_OK != ret)
    2288              :       {
    2289            0 :         GNUNET_break_op (0);
    2290            0 :         return GNUNET_SYSERR;
    2291              :       }
    2292           56 :       ptr++;
    2293              :     }
    2294              :   }
    2295           14 :   return GNUNET_OK;
    2296              : }
    2297              : 
    2298              : 
    2299              : struct GNUNET_JSON_Specification
    2300           14 : TALER_JSON_spec_array_of_blinded_denom_sigs (
    2301              :   const char *field,
    2302              :   size_t num_entries,
    2303              :   struct TALER_BlindedDenominationSignature *entries)
    2304              : {
    2305           14 :   struct GNUNET_JSON_Specification ret = {
    2306              :     .parser = &parse_array_of_blinded_denom_sigs,
    2307              :     .ptr = entries,
    2308              :     .field = field,
    2309           14 :     .cls = (void *) num_entries,
    2310              :   };
    2311              : 
    2312           70 :   for (size_t i = 0; i<num_entries; i++)
    2313           56 :     entries[i].blinded_sig = NULL;
    2314           14 :   return ret;
    2315              : }
    2316              : 
    2317              : 
    2318              : /* end of json/json_helper.c */
        

Generated by: LCOV version 2.0-1