LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.8 % 734 395
Test Date: 2025-12-26 23:00:34 Functions: 69.7 % 66 46

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

Generated by: LCOV version 2.0-1