LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.0 % 863 457
Test Date: 2026-10-29 19:05:17 Functions: 65.0 % 80 52

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

Generated by: LCOV version 2.0-1