LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 52.7 % 859 453
Test Date: 2026-10-01 12:53:39 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         1015 : string_to_cipher (const char *cipher_s)
      36              : {
      37         1015 :   if ((0 == strcasecmp (cipher_s,
      38          542 :                         "RSA")) ||
      39          542 :       (0 == strcasecmp (cipher_s,
      40              :                         "RSA+age_restricted")))
      41          548 :     return GNUNET_CRYPTO_BSA_RSA;
      42          467 :   if ((0 == strcasecmp (cipher_s,
      43           70 :                         "CS")) ||
      44           70 :       (0 == strcasecmp (cipher_s,
      45              :                         "CS+age_restricted")))
      46          467 :     return GNUNET_CRYPTO_BSA_CS;
      47            0 :   return GNUNET_CRYPTO_BSA_INVALID;
      48              : }
      49              : 
      50              : 
      51              : json_t *
      52         5508 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
      53              : {
      54         5508 :   char *amount_str = TALER_amount_to_string (amount);
      55              : 
      56         5508 :   GNUNET_assert (NULL != amount_str);
      57              :   {
      58         5508 :     json_t *j = json_string (amount_str);
      59              : 
      60         5508 :     GNUNET_free (amount_str);
      61         5508 :     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         7052 : parse_amount (void *cls,
      76              :               json_t *root,
      77              :               struct GNUNET_JSON_Specification *spec)
      78              : {
      79         7052 :   const char *currency = cls;
      80         7052 :   struct TALER_Amount *r_amount = spec->ptr;
      81              : 
      82              :   (void) cls;
      83         7052 :   if (! json_is_string (root))
      84              :   {
      85            0 :     GNUNET_break_op (0);
      86            0 :     return GNUNET_SYSERR;
      87              :   }
      88         7052 :   if (GNUNET_OK !=
      89         7052 :       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         7052 :   if ( (NULL != currency) &&
      96              :        (0 !=
      97         4951 :         strcasecmp (currency,
      98         4951 :                     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         7052 :   return GNUNET_OK;
     109              : }
     110              : 
     111              : 
     112              : struct GNUNET_JSON_Specification
     113         4980 : TALER_JSON_spec_amount (const char *name,
     114              :                         const char *currency,
     115              :                         struct TALER_Amount *r_amount)
     116              : {
     117         4980 :   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         4980 :   GNUNET_assert (NULL != currency);
     128         4980 :   return ret;
     129              : }
     130              : 
     131              : 
     132              : struct GNUNET_JSON_Specification
     133         2209 : TALER_JSON_spec_amount_any (const char *name,
     134              :                             struct TALER_Amount *r_amount)
     135              : {
     136         2209 :   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         2209 :   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           42 : parse_cspec (void *cls,
     377              :              json_t *root,
     378              :              struct GNUNET_JSON_Specification *spec)
     379              : {
     380           42 :   struct TALER_CurrencySpecification *r_cspec = spec->ptr;
     381           42 :   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           42 :   const json_t *ca = NULL;
     388              :   struct GNUNET_JSON_Specification gspec[] = {
     389           42 :     GNUNET_JSON_spec_string ("name",
     390              :                              &name),
     391           42 :     GNUNET_JSON_spec_uint32 ("num_fractional_input_digits",
     392              :                              &fid),
     393           42 :     GNUNET_JSON_spec_uint32 ("num_fractional_normal_digits",
     394              :                              &fnd),
     395           42 :     GNUNET_JSON_spec_uint32 ("num_fractional_trailing_zero_digits",
     396              :                              &ftzd),
     397           42 :     GNUNET_JSON_spec_object_const ("alt_unit_names",
     398              :                                    &map),
     399           42 :     GNUNET_JSON_spec_mark_optional (
     400              :       GNUNET_JSON_spec_array_const ("common_amounts",
     401              :                                     &ca),
     402              :       NULL),
     403           42 :     GNUNET_JSON_spec_end ()
     404              :   };
     405              :   const char *emsg;
     406              :   unsigned int eline;
     407              : 
     408           42 :   memset (r_cspec->currency,
     409              :           0,
     410              :           sizeof (r_cspec->currency));
     411           42 :   if (GNUNET_OK !=
     412           42 :       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           42 :   if (strlen (currency) >= TALER_CURRENCY_LEN)
     426              :   {
     427            0 :     GNUNET_break_op (0);
     428            0 :     return GNUNET_SYSERR;
     429              :   }
     430           42 :   if ( (fid > TALER_AMOUNT_FRAC_LEN) ||
     431           42 :        (fnd > TALER_AMOUNT_FRAC_LEN) ||
     432           42 :        (ftzd > TALER_AMOUNT_FRAC_LEN) )
     433              :   {
     434            0 :     GNUNET_break_op (0);
     435            0 :     return GNUNET_SYSERR;
     436              :   }
     437           42 :   if (GNUNET_OK !=
     438           42 :       TALER_check_currency (currency))
     439              :   {
     440            0 :     GNUNET_break_op (0);
     441            0 :     return GNUNET_SYSERR;
     442              :   }
     443           42 :   strcpy (r_cspec->currency,
     444              :           currency);
     445           42 :   if (GNUNET_OK !=
     446           42 :       TALER_check_currency_scale_map (map))
     447              :   {
     448            0 :     GNUNET_break_op (0);
     449            0 :     return GNUNET_SYSERR;
     450              :   }
     451           42 :   r_cspec->name = GNUNET_strdup (name);
     452           42 :   r_cspec->map_alt_unit_names = json_incref ((json_t *) map);
     453           42 :   if (NULL != ca)
     454              :   {
     455              :     size_t i;
     456              :     json_t *v;
     457              : 
     458          210 :     json_array_foreach ((json_t *) ca, i, v)
     459              :     {
     460              :       struct TALER_Amount val;
     461              :       const char *vstr;
     462              : 
     463          168 :       vstr = json_string_value (v);
     464          336 :       if ( (NULL == vstr) ||
     465              :            (GNUNET_OK !=
     466          168 :             TALER_string_to_amount (vstr,
     467              :                                     &val)) )
     468              :       {
     469            0 :         GNUNET_break_op (0);
     470            0 :         return GNUNET_SYSERR;
     471              :       }
     472          168 :       if (0 != strcasecmp (val.currency,
     473          168 :                            r_cspec->currency))
     474              :       {
     475            0 :         GNUNET_break_op (0);
     476            0 :         return GNUNET_SYSERR;
     477              :       }
     478          168 :       GNUNET_array_append (r_cspec->common_amounts,
     479              :                            r_cspec->num_common_amounts,
     480              :                            val);
     481              :     }
     482              :   }
     483           42 :   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           42 : TALER_JSON_spec_currency_specification (
     510              :   const char *name,
     511              :   const char *currency,
     512              :   struct TALER_CurrencySpecification *r_cspec)
     513              : {
     514           42 :   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           42 :   memset (r_cspec,
     525              :           0,
     526              :           sizeof (*r_cspec));
     527           42 :   return ret;
     528              : }
     529              : 
     530              : 
     531              : static enum GNUNET_GenericReturnValue
     532          309 : parse_denomination_group (void *cls,
     533              :                           json_t *root,
     534              :                           struct GNUNET_JSON_Specification *spec)
     535              : {
     536          309 :   struct TALER_DenominationGroup *group = spec->ptr;
     537              :   const char *cipher;
     538          309 :   const char *currency = cls;
     539          309 :   bool age_mask_missing = false;
     540          309 :   bool has_age_restricted_suffix = false;
     541              :   struct GNUNET_JSON_Specification gspec[] = {
     542          309 :     GNUNET_JSON_spec_string ("cipher",
     543              :                              &cipher),
     544          309 :     TALER_JSON_spec_amount ("value",
     545              :                             currency,
     546              :                             &group->value),
     547          309 :     TALER_JSON_SPEC_DENOM_FEES ("fee",
     548              :                                 currency,
     549              :                                 &group->fees),
     550          309 :     GNUNET_JSON_spec_mark_optional (
     551              :       GNUNET_JSON_spec_uint32 ("age_mask",
     552              :                                &group->age_mask.bits),
     553              :       &age_mask_missing),
     554          309 :     GNUNET_JSON_spec_end ()
     555              :   };
     556              :   const char *emsg;
     557              :   unsigned int eline;
     558              : 
     559          309 :   if (GNUNET_OK !=
     560          309 :       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          309 :   group->cipher = string_to_cipher (cipher);
     575          309 :   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          309 :   has_age_restricted_suffix =
     583          309 :     (NULL != strstr (cipher, "+age_restricted"));
     584          309 :   if (has_age_restricted_suffix && age_mask_missing)
     585              :   {
     586            0 :     GNUNET_break_op (0);
     587            0 :     return GNUNET_SYSERR;
     588              :   }
     589              : 
     590          309 :   if (age_mask_missing)
     591          164 :     group->age_mask.bits = 0;
     592              : 
     593          309 :   return GNUNET_OK;
     594              : }
     595              : 
     596              : 
     597              : struct GNUNET_JSON_Specification
     598          309 : TALER_JSON_spec_denomination_group (const char *name,
     599              :                                     const char *currency,
     600              :                                     struct TALER_DenominationGroup *group)
     601              : {
     602          309 :   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          309 :   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           25 : parse_econtract (void *cls,
     624              :                  json_t *root,
     625              :                  struct GNUNET_JSON_Specification *spec)
     626              : {
     627           25 :   struct TALER_EncryptedContract *econtract = spec->ptr;
     628              :   struct GNUNET_JSON_Specification ispec[] = {
     629           25 :     GNUNET_JSON_spec_varsize ("econtract",
     630              :                               &econtract->econtract,
     631              :                               &econtract->econtract_size),
     632           25 :     GNUNET_JSON_spec_fixed_auto ("econtract_sig",
     633              :                                  &econtract->econtract_sig),
     634           25 :     GNUNET_JSON_spec_fixed_auto ("contract_pub",
     635              :                                  &econtract->contract_pub),
     636           25 :     GNUNET_JSON_spec_end ()
     637              :   };
     638              :   const char *emsg;
     639              :   unsigned int eline;
     640              : 
     641              :   (void) cls;
     642           25 :   if (GNUNET_OK !=
     643           25 :       GNUNET_JSON_parse (root,
     644              :                          ispec,
     645              :                          &emsg,
     646              :                          &eline))
     647              :   {
     648            0 :     GNUNET_break_op (0);
     649            0 :     return GNUNET_SYSERR;
     650              :   }
     651           25 :   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           11 : clean_econtract (void *cls,
     663              :                  struct GNUNET_JSON_Specification *spec)
     664              : {
     665           11 :   struct TALER_EncryptedContract *econtract = spec->ptr;
     666              : 
     667              :   (void) cls;
     668           11 :   GNUNET_free (econtract->econtract);
     669           11 : }
     670              : 
     671              : 
     672              : struct GNUNET_JSON_Specification
     673           25 : TALER_JSON_spec_econtract (const char *name,
     674              :                            struct TALER_EncryptedContract *econtract)
     675              : {
     676           25 :   struct GNUNET_JSON_Specification ret = {
     677              :     .parser = &parse_econtract,
     678              :     .cleaner = &clean_econtract,
     679              :     .field = name,
     680              :     .ptr = econtract
     681              :   };
     682              : 
     683           25 :   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           14 : clean_age_commitment (void *cls,
     760              :                       struct GNUNET_JSON_Specification *spec)
     761              : {
     762           14 :   struct TALER_AgeCommitment *age_commitment = spec->ptr;
     763              : 
     764              :   (void) cls;
     765           14 :   if ( (NULL == age_commitment) ||
     766           14 :        (NULL == age_commitment->pubs) )
     767            6 :     return;
     768            8 :   age_commitment->num = 0;
     769            8 :   GNUNET_free (age_commitment->pubs);
     770              : }
     771              : 
     772              : 
     773              : struct GNUNET_JSON_Specification
     774           34 : TALER_JSON_spec_age_commitment (const char *name,
     775              :                                 struct TALER_AgeCommitment *age_commitment)
     776              : {
     777           34 :   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           34 :   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          706 : parse_denom_pub (void *cls,
     829              :                  json_t *root,
     830              :                  struct GNUNET_JSON_Specification *spec)
     831              : {
     832          706 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     833              :   struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
     834              :   const char *cipher;
     835          706 :   bool age_mask_missing = false;
     836              :   struct GNUNET_JSON_Specification dspec[] = {
     837          706 :     GNUNET_JSON_spec_string ("cipher",
     838              :                              &cipher),
     839          706 :     GNUNET_JSON_spec_mark_optional (
     840              :       GNUNET_JSON_spec_uint32 ("age_mask",
     841              :                                &denom_pub->age_mask.bits),
     842              :       &age_mask_missing),
     843          706 :     GNUNET_JSON_spec_end ()
     844              :   };
     845              :   const char *emsg;
     846              :   unsigned int eline;
     847              : 
     848              :   (void) cls;
     849          706 :   if (GNUNET_OK !=
     850          706 :       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          706 :   if (age_mask_missing)
     860            0 :     denom_pub->age_mask.bits = 0;
     861          706 :   bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     862          706 :   bsign_pub->rc = 1;
     863          706 :   bsign_pub->cipher = string_to_cipher (cipher);
     864          706 :   switch (bsign_pub->cipher)
     865              :   {
     866            0 :   case GNUNET_CRYPTO_BSA_INVALID:
     867            0 :     break;
     868          388 :   case GNUNET_CRYPTO_BSA_RSA:
     869              :     {
     870              :       struct GNUNET_JSON_Specification ispec[] = {
     871          388 :         GNUNET_JSON_spec_rsa_public_key (
     872              :           "rsa_pub",
     873              :           &bsign_pub->details.rsa_public_key),
     874          388 :         GNUNET_JSON_spec_end ()
     875              :       };
     876              : 
     877          388 :       if (GNUNET_OK !=
     878          388 :           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          388 :       denom_pub->bsign_pub_key = bsign_pub;
     888          388 :       return GNUNET_OK;
     889              :     }
     890          318 :   case GNUNET_CRYPTO_BSA_CS:
     891              :     {
     892              :       struct GNUNET_JSON_Specification ispec[] = {
     893          318 :         GNUNET_JSON_spec_fixed ("cs_pub",
     894          318 :                                 &bsign_pub->details.cs_public_key,
     895              :                                 sizeof (bsign_pub->details.cs_public_key)),
     896          318 :         GNUNET_JSON_spec_end ()
     897              :       };
     898              : 
     899          318 :       if (GNUNET_OK !=
     900          318 :           GNUNET_JSON_parse (root,
     901              :                              ispec,
     902              :                              &emsg,
     903              :                              &eline))
     904              :       {
     905            0 :         GNUNET_break_op (0);
     906            0 :         GNUNET_free (bsign_pub);
     907            0 :         return GNUNET_SYSERR;
     908              :       }
     909          318 :       denom_pub->bsign_pub_key = bsign_pub;
     910          318 :       return GNUNET_OK;
     911              :     }
     912              :   }
     913            0 :   GNUNET_break_op (0);
     914            0 :   GNUNET_free (bsign_pub);
     915            0 :   return GNUNET_SYSERR;
     916              : }
     917              : 
     918              : 
     919              : /**
     920              :  * Cleanup data left from parsing denomination public key.
     921              :  *
     922              :  * @param cls closure, NULL
     923              :  * @param[out] spec where to free the data
     924              :  */
     925              : static void
     926          533 : clean_denom_pub (void *cls,
     927              :                  struct GNUNET_JSON_Specification *spec)
     928              : {
     929          533 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     930              : 
     931              :   (void) cls;
     932          533 :   TALER_denom_pub_free (denom_pub);
     933          533 : }
     934              : 
     935              : 
     936              : struct GNUNET_JSON_Specification
     937          706 : TALER_JSON_spec_denom_pub (const char *field,
     938              :                            struct TALER_DenominationPublicKey *pk)
     939              : {
     940          706 :   struct GNUNET_JSON_Specification ret = {
     941              :     .parser = &parse_denom_pub,
     942              :     .cleaner = &clean_denom_pub,
     943              :     .field = field,
     944              :     .ptr = pk
     945              :   };
     946              : 
     947          706 :   pk->bsign_pub_key = NULL;
     948          706 :   return ret;
     949              : }
     950              : 
     951              : 
     952              : /**
     953              :  * Parse given JSON object to token issue public key.
     954              :  *
     955              :  * @param cls closure, NULL
     956              :  * @param root the json object representing data
     957              :  * @param[out] spec where to write the data
     958              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     959              :  */
     960              : static enum GNUNET_GenericReturnValue
     961            0 : parse_token_pub (void *cls,
     962              :                  json_t *root,
     963              :                  struct GNUNET_JSON_Specification *spec)
     964              : {
     965            0 :   struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
     966              :   struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
     967              :   const char *cipher;
     968              :   struct GNUNET_JSON_Specification dspec[] = {
     969            0 :     GNUNET_JSON_spec_string ("cipher",
     970              :                              &cipher),
     971            0 :     GNUNET_JSON_spec_end ()
     972              :   };
     973              :   const char *emsg;
     974              :   unsigned int eline;
     975              : 
     976              :   (void) cls;
     977            0 :   if (GNUNET_OK !=
     978            0 :       GNUNET_JSON_parse (root,
     979              :                          dspec,
     980              :                          &emsg,
     981              :                          &eline))
     982              :   {
     983            0 :     GNUNET_break_op (0);
     984            0 :     return GNUNET_SYSERR;
     985              :   }
     986              : 
     987            0 :   bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     988            0 :   bsign_pub->rc = 1;
     989            0 :   bsign_pub->cipher = string_to_cipher (cipher);
     990            0 :   switch (bsign_pub->cipher)
     991              :   {
     992            0 :   case GNUNET_CRYPTO_BSA_INVALID:
     993            0 :     break;
     994            0 :   case GNUNET_CRYPTO_BSA_RSA:
     995              :     {
     996              :       struct GNUNET_JSON_Specification ispec[] = {
     997            0 :         GNUNET_JSON_spec_rsa_public_key (
     998              :           "rsa_pub",
     999              :           &bsign_pub->details.rsa_public_key),
    1000            0 :         GNUNET_JSON_spec_end ()
    1001              :       };
    1002              : 
    1003            0 :       if (GNUNET_OK !=
    1004            0 :           GNUNET_JSON_parse (root,
    1005              :                              ispec,
    1006              :                              &emsg,
    1007              :                              &eline))
    1008              :       {
    1009            0 :         GNUNET_break_op (0);
    1010            0 :         GNUNET_free (bsign_pub);
    1011            0 :         return GNUNET_SYSERR;
    1012              :       }
    1013            0 :       GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key,
    1014              :                                          &bsign_pub->pub_key_hash);
    1015            0 :       token_pub->public_key = bsign_pub;
    1016            0 :       return GNUNET_OK;
    1017              :     }
    1018            0 :   case GNUNET_CRYPTO_BSA_CS:
    1019              :     {
    1020              :       struct GNUNET_JSON_Specification ispec[] = {
    1021            0 :         GNUNET_JSON_spec_fixed ("cs_pub",
    1022            0 :                                 &bsign_pub->details.cs_public_key,
    1023              :                                 sizeof (bsign_pub->details.cs_public_key)),
    1024            0 :         GNUNET_JSON_spec_end ()
    1025              :       };
    1026              : 
    1027            0 :       if (GNUNET_OK !=
    1028            0 :           GNUNET_JSON_parse (root,
    1029              :                              ispec,
    1030              :                              &emsg,
    1031              :                              &eline))
    1032              :       {
    1033            0 :         GNUNET_break_op (0);
    1034            0 :         GNUNET_free (bsign_pub);
    1035            0 :         return GNUNET_SYSERR;
    1036              :       }
    1037            0 :       GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
    1038              :                           sizeof(bsign_pub->details.cs_public_key),
    1039              :                           &bsign_pub->pub_key_hash);
    1040            0 :       token_pub->public_key = bsign_pub;
    1041            0 :       return GNUNET_OK;
    1042              :     }
    1043              :   }
    1044            0 :   GNUNET_break_op (0);
    1045            0 :   GNUNET_free (bsign_pub);
    1046            0 :   return GNUNET_SYSERR;
    1047              : }
    1048              : 
    1049              : 
    1050              : /**
    1051              :  * Cleanup data left from parsing token issue public key.
    1052              :  *
    1053              :  * @param cls closure, NULL
    1054              :  * @param[out] spec where to free the data
    1055              :  */
    1056              : static void
    1057            0 : clean_token_pub (void *cls,
    1058              :                  struct GNUNET_JSON_Specification *spec)
    1059              : {
    1060            0 :   struct TALER_TokenIssuePublicKey *token_pub = spec->ptr;
    1061              : 
    1062              :   (void) cls;
    1063            0 :   TALER_token_issue_pub_free (token_pub);
    1064            0 : }
    1065              : 
    1066              : 
    1067              : struct GNUNET_JSON_Specification
    1068            0 : TALER_JSON_spec_token_pub (const char *field,
    1069              :                            struct TALER_TokenIssuePublicKey *pk)
    1070              : {
    1071            0 :   struct GNUNET_JSON_Specification ret = {
    1072              :     .field = field,
    1073              :     .parser = &parse_token_pub,
    1074              :     .cleaner = &clean_token_pub,
    1075              :     .ptr = pk
    1076              :   };
    1077              : 
    1078            0 :   pk->public_key = NULL;
    1079            0 :   return ret;
    1080              : }
    1081              : 
    1082              : 
    1083              : /**
    1084              :  * Parse given JSON object partially into a denomination public key.
    1085              :  *
    1086              :  * Depending on the cipher in cls, it parses the corresponding public key type.
    1087              :  *
    1088              :  * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm
    1089              :  * @param root the json object representing data
    1090              :  * @param[out] spec where to write the data
    1091              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1092              :  */
    1093              : static enum GNUNET_GenericReturnValue
    1094          890 : parse_denom_pub_cipher (void *cls,
    1095              :                         json_t *root,
    1096              :                         struct GNUNET_JSON_Specification *spec)
    1097              : {
    1098          890 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
    1099          890 :   enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher =
    1100          890 :     (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls;
    1101              :   struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
    1102              :   const char *emsg;
    1103              :   unsigned int eline;
    1104              : 
    1105          890 :   bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
    1106          890 :   bsign_pub->cipher = cipher;
    1107          890 :   bsign_pub->rc = 1;
    1108          890 :   switch (cipher)
    1109              :   {
    1110            0 :   case GNUNET_CRYPTO_BSA_INVALID:
    1111            0 :     break;
    1112          460 :   case GNUNET_CRYPTO_BSA_RSA:
    1113              :     {
    1114              :       struct GNUNET_JSON_Specification ispec[] = {
    1115          460 :         GNUNET_JSON_spec_rsa_public_key (
    1116              :           "rsa_pub",
    1117              :           &bsign_pub->details.rsa_public_key),
    1118          460 :         GNUNET_JSON_spec_end ()
    1119              :       };
    1120              : 
    1121          460 :       if (GNUNET_OK !=
    1122          460 :           GNUNET_JSON_parse (root,
    1123              :                              ispec,
    1124              :                              &emsg,
    1125              :                              &eline))
    1126              :       {
    1127            0 :         GNUNET_break_op (0);
    1128            0 :         GNUNET_free (bsign_pub);
    1129            0 :         return GNUNET_SYSERR;
    1130              :       }
    1131          460 :       denom_pub->bsign_pub_key = bsign_pub;
    1132          460 :       return GNUNET_OK;
    1133              :     }
    1134          430 :   case GNUNET_CRYPTO_BSA_CS:
    1135              :     {
    1136              :       struct GNUNET_JSON_Specification ispec[] = {
    1137          430 :         GNUNET_JSON_spec_fixed ("cs_pub",
    1138          430 :                                 &bsign_pub->details.cs_public_key,
    1139              :                                 sizeof (bsign_pub->details.cs_public_key)),
    1140          430 :         GNUNET_JSON_spec_end ()
    1141              :       };
    1142              : 
    1143          430 :       if (GNUNET_OK !=
    1144          430 :           GNUNET_JSON_parse (root,
    1145              :                              ispec,
    1146              :                              &emsg,
    1147              :                              &eline))
    1148              :       {
    1149            0 :         GNUNET_break_op (0);
    1150            0 :         GNUNET_free (bsign_pub);
    1151            0 :         return GNUNET_SYSERR;
    1152              :       }
    1153          430 :       denom_pub->bsign_pub_key = bsign_pub;
    1154          430 :       return GNUNET_OK;
    1155              :     }
    1156              :   }
    1157            0 :   GNUNET_break_op (0);
    1158            0 :   GNUNET_free (bsign_pub);
    1159            0 :   return GNUNET_SYSERR;
    1160              : }
    1161              : 
    1162              : 
    1163              : struct GNUNET_JSON_Specification
    1164          890 : TALER_JSON_spec_denom_pub_cipher (
    1165              :   const char *field,
    1166              :   enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
    1167              :   struct TALER_DenominationPublicKey *pk)
    1168              : {
    1169          890 :   struct GNUNET_JSON_Specification ret = {
    1170              :     .parser = &parse_denom_pub_cipher,
    1171              :     .cleaner = &clean_denom_pub,
    1172              :     .field = field,
    1173          890 :     .cls = (void *) cipher,
    1174              :     .ptr = pk
    1175              :   };
    1176              : 
    1177          890 :   pk->bsign_pub_key = NULL;
    1178          890 :   return ret;
    1179              : }
    1180              : 
    1181              : 
    1182              : struct GNUNET_JSON_Specification
    1183          150 : TALER_JSON_spec_denom_sig (const char *field,
    1184              :                            struct TALER_DenominationSignature *sig)
    1185              : {
    1186          150 :   sig->unblinded_sig = NULL;
    1187          150 :   return GNUNET_JSON_spec_unblinded_signature (field,
    1188              :                                                &sig->unblinded_sig);
    1189              : }
    1190              : 
    1191              : 
    1192              : struct GNUNET_JSON_Specification
    1193          126 : TALER_JSON_spec_blinded_denom_sig (
    1194              :   const char *field,
    1195              :   struct TALER_BlindedDenominationSignature *sig)
    1196              : {
    1197          126 :   sig->blinded_sig = NULL;
    1198          126 :   return GNUNET_JSON_spec_blinded_signature (field,
    1199              :                                              &sig->blinded_sig);
    1200              : }
    1201              : 
    1202              : 
    1203              : struct GNUNET_JSON_Specification
    1204          459 : TALER_JSON_spec_blinded_planchet (
    1205              :   const char *field,
    1206              :   struct TALER_BlindedPlanchet *blinded_planchet)
    1207              : {
    1208          459 :   blinded_planchet->blinded_message = NULL;
    1209          459 :   return GNUNET_JSON_spec_blinded_message (field,
    1210              :                                            &blinded_planchet->blinded_message);
    1211              : }
    1212              : 
    1213              : 
    1214              : /**
    1215              :  * Parse given JSON object to exchange withdraw values (/csr).
    1216              :  *
    1217              :  * @param cls closure, NULL
    1218              :  * @param root the json object representing data
    1219              :  * @param[out] spec where to write the data
    1220              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1221              :  */
    1222              : static enum GNUNET_GenericReturnValue
    1223            0 : parse_exchange_blinding_values (void *cls,
    1224              :                                 json_t *root,
    1225              :                                 struct GNUNET_JSON_Specification *spec)
    1226              : {
    1227            0 :   struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
    1228              :   struct GNUNET_CRYPTO_BlindingInputValues *bi;
    1229              :   const char *cipher;
    1230              :   struct GNUNET_JSON_Specification dspec[] = {
    1231            0 :     GNUNET_JSON_spec_string ("cipher",
    1232              :                              &cipher),
    1233            0 :     GNUNET_JSON_spec_end ()
    1234              :   };
    1235              :   const char *emsg;
    1236              :   unsigned int eline;
    1237              :   enum GNUNET_CRYPTO_BlindSignatureAlgorithm ci;
    1238              : 
    1239              :   (void) cls;
    1240            0 :   if (GNUNET_OK !=
    1241            0 :       GNUNET_JSON_parse (root,
    1242              :                          dspec,
    1243              :                          &emsg,
    1244              :                          &eline))
    1245              :   {
    1246            0 :     GNUNET_break_op (0);
    1247            0 :     return GNUNET_SYSERR;
    1248              :   }
    1249            0 :   ci = string_to_cipher (cipher);
    1250            0 :   switch (ci)
    1251              :   {
    1252            0 :   case GNUNET_CRYPTO_BSA_INVALID:
    1253            0 :     break;
    1254            0 :   case GNUNET_CRYPTO_BSA_RSA:
    1255            0 :     ewv->blinding_inputs = TALER_denom_ewv_rsa_singleton ()->blinding_inputs;
    1256            0 :     return GNUNET_OK;
    1257            0 :   case GNUNET_CRYPTO_BSA_CS:
    1258            0 :     bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
    1259            0 :     bi->cipher = GNUNET_CRYPTO_BSA_CS;
    1260            0 :     bi->rc = 1;
    1261              :     {
    1262              :       struct GNUNET_JSON_Specification ispec[] = {
    1263            0 :         GNUNET_JSON_spec_fixed (
    1264              :           "r_pub_0",
    1265            0 :           &bi->details.cs_values.r_pub[0],
    1266              :           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
    1267            0 :         GNUNET_JSON_spec_fixed (
    1268              :           "r_pub_1",
    1269            0 :           &bi->details.cs_values.r_pub[1],
    1270              :           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
    1271            0 :         GNUNET_JSON_spec_end ()
    1272              :       };
    1273              : 
    1274            0 :       if (GNUNET_OK !=
    1275            0 :           GNUNET_JSON_parse (root,
    1276              :                              ispec,
    1277              :                              &emsg,
    1278              :                              &eline))
    1279              :       {
    1280            0 :         GNUNET_break_op (0);
    1281            0 :         GNUNET_free (bi);
    1282            0 :         return GNUNET_SYSERR;
    1283              :       }
    1284            0 :       ewv->blinding_inputs = bi;
    1285            0 :       return GNUNET_OK;
    1286              :     }
    1287              :   }
    1288            0 :   GNUNET_break_op (0);
    1289            0 :   return GNUNET_SYSERR;
    1290              : }
    1291              : 
    1292              : 
    1293              : /**
    1294              :  * Cleanup data left from parsing withdraw values
    1295              :  *
    1296              :  * @param cls closure, NULL
    1297              :  * @param[out] spec where to free the data
    1298              :  */
    1299              : static void
    1300            0 : clean_exchange_blinding_values (
    1301              :   void *cls,
    1302              :   struct GNUNET_JSON_Specification *spec)
    1303              : {
    1304            0 :   struct TALER_ExchangeBlindingValues *ewv = spec->ptr;
    1305              : 
    1306              :   (void) cls;
    1307            0 :   TALER_denom_ewv_free (ewv);
    1308            0 : }
    1309              : 
    1310              : 
    1311              : struct GNUNET_JSON_Specification
    1312            0 : TALER_JSON_spec_exchange_blinding_values (
    1313              :   const char *field,
    1314              :   struct TALER_ExchangeBlindingValues *ewv)
    1315              : {
    1316            0 :   struct GNUNET_JSON_Specification ret = {
    1317              :     .parser = &parse_exchange_blinding_values,
    1318              :     .cleaner = &clean_exchange_blinding_values,
    1319              :     .field = field,
    1320              :     .ptr = ewv
    1321              :   };
    1322              : 
    1323            0 :   ewv->blinding_inputs = NULL;
    1324            0 :   return ret;
    1325              : }
    1326              : 
    1327              : 
    1328              : /**
    1329              :  * Closure for #parse_i18n_string.
    1330              :  */
    1331              : struct I18nContext
    1332              : {
    1333              :   /**
    1334              :    * Language pattern to match.
    1335              :    */
    1336              :   char *lp;
    1337              : 
    1338              :   /**
    1339              :    * Name of the field to match.
    1340              :    */
    1341              :   const char *field;
    1342              : };
    1343              : 
    1344              : 
    1345              : /**
    1346              :  * Parse given JSON object to internationalized string.
    1347              :  *
    1348              :  * @param cls closure, our `struct I18nContext *`
    1349              :  * @param root the json object representing data
    1350              :  * @param[out] spec where to write the data
    1351              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1352              :  */
    1353              : static enum GNUNET_GenericReturnValue
    1354            0 : parse_i18n_string (void *cls,
    1355              :                    json_t *root,
    1356              :                    struct GNUNET_JSON_Specification *spec)
    1357              : {
    1358            0 :   struct I18nContext *ctx = cls;
    1359              :   json_t *i18n;
    1360              :   json_t *val;
    1361              : 
    1362              :   {
    1363              :     char *i18nf;
    1364              : 
    1365            0 :     GNUNET_asprintf (&i18nf,
    1366              :                      "%s_i18n",
    1367              :                      ctx->field);
    1368            0 :     i18n = json_object_get (root,
    1369              :                             i18nf);
    1370            0 :     GNUNET_free (i18nf);
    1371              :   }
    1372              : 
    1373            0 :   val = json_object_get (root,
    1374              :                          ctx->field);
    1375            0 :   if ( (NULL != i18n) &&
    1376            0 :        (NULL != ctx->lp) )
    1377              :   {
    1378            0 :     double best = 0.0;
    1379              :     json_t *pos;
    1380              :     const char *lang;
    1381              : 
    1382            0 :     json_object_foreach (i18n, lang, pos)
    1383              :     {
    1384              :       double score;
    1385              : 
    1386            0 :       score = TALER_pattern_matches (ctx->lp,
    1387              :                                      lang);
    1388            0 :       if (score > best)
    1389              :       {
    1390            0 :         best = score;
    1391            0 :         val = pos;
    1392              :       }
    1393              :     }
    1394              :   }
    1395              : 
    1396              :   {
    1397              :     const char *str;
    1398              : 
    1399            0 :     str = json_string_value (val);
    1400            0 :     *(const char **) spec->ptr = str;
    1401              :   }
    1402            0 :   return GNUNET_OK;
    1403              : }
    1404              : 
    1405              : 
    1406              : /**
    1407              :  * Function called to clean up data from earlier parsing.
    1408              :  *
    1409              :  * @param cls closure
    1410              :  * @param spec our specification entry with data to clean.
    1411              :  */
    1412              : static void
    1413            0 : i18n_cleaner (void *cls,
    1414              :               struct GNUNET_JSON_Specification *spec)
    1415              : {
    1416            0 :   struct I18nContext *ctx = cls;
    1417              : 
    1418              :   (void) spec;
    1419            0 :   if (NULL != ctx)
    1420              :   {
    1421            0 :     GNUNET_free (ctx->lp);
    1422            0 :     GNUNET_free (ctx);
    1423              :   }
    1424            0 : }
    1425              : 
    1426              : 
    1427              : struct GNUNET_JSON_Specification
    1428            0 : TALER_JSON_spec_i18n_string (const char *name,
    1429              :                              const char *language_pattern,
    1430              :                              const char **strptr)
    1431              : {
    1432            0 :   struct I18nContext *ctx = GNUNET_new (struct I18nContext);
    1433            0 :   struct GNUNET_JSON_Specification ret = {
    1434              :     .parser = &parse_i18n_string,
    1435              :     .cleaner = &i18n_cleaner,
    1436              :     .cls = ctx,
    1437              :     .field = NULL, /* we want the main object */
    1438              :     .ptr = strptr,
    1439              :     .ptr_size = 0,
    1440              :     .size_ptr = NULL
    1441              :   };
    1442              : 
    1443            0 :   ctx->lp = (NULL != language_pattern)
    1444            0 :     ? GNUNET_strdup (language_pattern)
    1445            0 :     : NULL;
    1446            0 :   ctx->field = name;
    1447            0 :   *strptr = NULL;
    1448            0 :   return ret;
    1449              : }
    1450              : 
    1451              : 
    1452              : struct GNUNET_JSON_Specification
    1453            0 : TALER_JSON_spec_i18n_str (const char *name,
    1454              :                           const char **strptr)
    1455              : {
    1456            0 :   const char *lang = getenv ("LANG");
    1457              :   const char *dot;
    1458              :   char *l;
    1459              :   struct GNUNET_JSON_Specification ret;
    1460              : 
    1461            0 :   if (NULL != lang)
    1462              :   {
    1463            0 :     dot = strchr (lang,
    1464              :                   '.');
    1465            0 :     if (NULL == dot)
    1466            0 :       l = GNUNET_strdup (lang);
    1467              :     else
    1468            0 :       l = GNUNET_strndup (lang,
    1469              :                           dot - lang);
    1470              :   }
    1471              :   else
    1472              :   {
    1473            0 :     l = NULL;
    1474              :   }
    1475            0 :   ret = TALER_JSON_spec_i18n_string (name,
    1476              :                                      l,
    1477              :                                      strptr);
    1478            0 :   GNUNET_free (l);
    1479            0 :   return ret;
    1480              : }
    1481              : 
    1482              : 
    1483              : /**
    1484              :  * Parse given JSON object with Taler error code.
    1485              :  *
    1486              :  * @param cls closure, NULL
    1487              :  * @param root the json object representing data
    1488              :  * @param[out] spec where to write the data
    1489              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1490              :  */
    1491              : static enum GNUNET_GenericReturnValue
    1492            0 : parse_ec (void *cls,
    1493              :           json_t *root,
    1494              :           struct GNUNET_JSON_Specification *spec)
    1495              : {
    1496            0 :   enum TALER_ErrorCode *ec = spec->ptr;
    1497              :   json_int_t num;
    1498              : 
    1499              :   (void) cls;
    1500            0 :   if (! json_is_integer (root))
    1501              :   {
    1502            0 :     GNUNET_break_op (0);
    1503            0 :     return GNUNET_SYSERR;
    1504              :   }
    1505            0 :   num = json_integer_value (root);
    1506            0 :   if (num < 0)
    1507              :   {
    1508            0 :     GNUNET_break_op (0);
    1509            0 :     *ec = TALER_EC_INVALID;
    1510            0 :     return GNUNET_SYSERR;
    1511              :   }
    1512            0 :   *ec = (enum TALER_ErrorCode) num;
    1513            0 :   return GNUNET_OK;
    1514              : }
    1515              : 
    1516              : 
    1517              : struct GNUNET_JSON_Specification
    1518            0 : TALER_JSON_spec_ec (const char *field,
    1519              :                     enum TALER_ErrorCode *ec)
    1520              : {
    1521            0 :   struct GNUNET_JSON_Specification ret = {
    1522              :     .parser = &parse_ec,
    1523              :     .field = field,
    1524              :     .ptr = ec
    1525              :   };
    1526              : 
    1527            0 :   *ec = TALER_EC_NONE;
    1528            0 :   return ret;
    1529              : }
    1530              : 
    1531              : 
    1532              : /**
    1533              :  * Parse given JSON object to web URL.
    1534              :  *
    1535              :  * @param cls closure, NULL
    1536              :  * @param root the json object representing data
    1537              :  * @param[out] spec where to write the data
    1538              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1539              :  */
    1540              : static enum GNUNET_GenericReturnValue
    1541          105 : parse_web_url (void *cls,
    1542              :                json_t *root,
    1543              :                struct GNUNET_JSON_Specification *spec)
    1544              : {
    1545              :   const char *str;
    1546              : 
    1547              :   (void) cls;
    1548          105 :   str = json_string_value (root);
    1549          105 :   if (NULL == str)
    1550              :   {
    1551            0 :     GNUNET_break_op (0);
    1552            0 :     return GNUNET_SYSERR;
    1553              :   }
    1554          105 :   if (! TALER_is_web_url (str))
    1555              :   {
    1556            0 :     GNUNET_break_op (0);
    1557            0 :     return GNUNET_SYSERR;
    1558              :   }
    1559          105 :   *(const char **) spec->ptr = str;
    1560          105 :   return GNUNET_OK;
    1561              : }
    1562              : 
    1563              : 
    1564              : struct GNUNET_JSON_Specification
    1565          497 : TALER_JSON_spec_web_url (const char *field,
    1566              :                          const char **url)
    1567              : {
    1568          497 :   struct GNUNET_JSON_Specification ret = {
    1569              :     .parser = &parse_web_url,
    1570              :     .field = field,
    1571              :     .ptr = url
    1572              :   };
    1573              : 
    1574          497 :   *url = NULL;
    1575          497 :   return ret;
    1576              : }
    1577              : 
    1578              : 
    1579              : /**
    1580              :  * Parse given JSON object to web URL, and make a copy.
    1581              :  *
    1582              :  * @param cls closure, NULL
    1583              :  * @param root the json object representing data
    1584              :  * @param[out] spec where to write the data
    1585              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1586              :  */
    1587              : static enum GNUNET_GenericReturnValue
    1588            0 : parse_web_url_copy (void *cls,
    1589              :                     json_t *root,
    1590              :                     struct GNUNET_JSON_Specification *spec)
    1591              : {
    1592              :   const char *str;
    1593              : 
    1594              :   (void) cls;
    1595            0 :   str = json_string_value (root);
    1596            0 :   if (NULL == str)
    1597              :   {
    1598            0 :     GNUNET_break_op (0);
    1599            0 :     return GNUNET_SYSERR;
    1600              :   }
    1601            0 :   if (! TALER_is_web_url (str))
    1602              :   {
    1603            0 :     GNUNET_break_op (0);
    1604            0 :     return GNUNET_SYSERR;
    1605              :   }
    1606            0 :   *(char **) spec->ptr = GNUNET_strdup (str);
    1607            0 :   return GNUNET_OK;
    1608              : }
    1609              : 
    1610              : 
    1611              : struct GNUNET_JSON_Specification
    1612            0 : TALER_JSON_spec_web_url_copy (const char *field,
    1613              :                               char **url)
    1614              : {
    1615            0 :   struct GNUNET_JSON_Specification ret = {
    1616              :     .parser = &parse_web_url_copy,
    1617              :     .field = field,
    1618              :     .ptr = url
    1619              :   };
    1620              : 
    1621            0 :   *url = NULL;
    1622            0 :   return ret;
    1623              : }
    1624              : 
    1625              : 
    1626              : /**
    1627              :  * Parse given JSON object to slug.
    1628              :  *
    1629              :  * @param cls closure, NULL
    1630              :  * @param root the json object representing data
    1631              :  * @param[out] spec where to write the data
    1632              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1633              :  */
    1634              : static enum GNUNET_GenericReturnValue
    1635           14 : parse_slug (void *cls,
    1636              :             json_t *root,
    1637              :             struct GNUNET_JSON_Specification *spec)
    1638              : {
    1639              :   const char *str;
    1640              : 
    1641              :   (void) cls;
    1642           14 :   str = json_string_value (root);
    1643           14 :   if (NULL == str)
    1644              :   {
    1645            0 :     GNUNET_break_op (0);
    1646            0 :     return GNUNET_SYSERR;
    1647              :   }
    1648           14 :   if (! TALER_is_slug (str))
    1649              :   {
    1650            0 :     GNUNET_break_op (0);
    1651            0 :     return GNUNET_SYSERR;
    1652              :   }
    1653           14 :   *(const char **) spec->ptr = str;
    1654           14 :   return GNUNET_OK;
    1655              : }
    1656              : 
    1657              : 
    1658              : struct GNUNET_JSON_Specification
    1659           14 : TALER_JSON_spec_slug (const char *field,
    1660              :                       const char **slug)
    1661              : {
    1662           14 :   struct GNUNET_JSON_Specification ret = {
    1663              :     .parser = &parse_slug,
    1664              :     .field = field,
    1665              :     .ptr = slug
    1666              :   };
    1667              : 
    1668           14 :   *slug = NULL;
    1669           14 :   return ret;
    1670              : }
    1671              : 
    1672              : 
    1673              : /**
    1674              :  * Parse given JSON object to slug.
    1675              :  *
    1676              :  * @param cls closure, NULL
    1677              :  * @param root the json object representing data
    1678              :  * @param[out] spec where to write the data
    1679              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1680              :  */
    1681              : static enum GNUNET_GenericReturnValue
    1682            0 : parse_slug_copy (void *cls,
    1683              :                  json_t *root,
    1684              :                  struct GNUNET_JSON_Specification *spec)
    1685              : {
    1686              :   const char *str;
    1687              : 
    1688              :   (void) cls;
    1689            0 :   str = json_string_value (root);
    1690            0 :   if (NULL == str)
    1691              :   {
    1692            0 :     GNUNET_break_op (0);
    1693            0 :     return GNUNET_SYSERR;
    1694              :   }
    1695            0 :   if (! TALER_is_slug (str))
    1696              :   {
    1697            0 :     GNUNET_break_op (0);
    1698            0 :     return GNUNET_SYSERR;
    1699              :   }
    1700            0 :   *(char **) spec->ptr = GNUNET_strdup (str);
    1701            0 :   return GNUNET_OK;
    1702              : }
    1703              : 
    1704              : 
    1705              : struct GNUNET_JSON_Specification
    1706            0 : TALER_JSON_spec_slug_copy (const char *field,
    1707              :                            char **slug)
    1708              : {
    1709            0 :   struct GNUNET_JSON_Specification ret = {
    1710              :     .parser = &parse_slug_copy,
    1711              :     .field = field,
    1712              :     .ptr = slug
    1713              :   };
    1714              : 
    1715            0 :   *slug = NULL;
    1716            0 :   return ret;
    1717              : }
    1718              : 
    1719              : 
    1720              : /**
    1721              :  * Parse given JSON object to a session ID.
    1722              :  *
    1723              :  * @param cls closure, NULL
    1724              :  * @param root the json object representing data
    1725              :  * @param[out] spec where to write the data
    1726              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1727              :  */
    1728              : static enum GNUNET_GenericReturnValue
    1729            0 : parse_session_id (void *cls,
    1730              :                   json_t *root,
    1731              :                   struct GNUNET_JSON_Specification *spec)
    1732              : {
    1733              :   const char *str;
    1734              : 
    1735              :   (void) cls;
    1736            0 :   str = json_string_value (root);
    1737            0 :   if (NULL == str)
    1738              :   {
    1739            0 :     GNUNET_break_op (0);
    1740            0 :     return GNUNET_SYSERR;
    1741              :   }
    1742            0 :   if (! TALER_is_session_id (str))
    1743              :   {
    1744            0 :     GNUNET_break_op (0);
    1745            0 :     return GNUNET_SYSERR;
    1746              :   }
    1747            0 :   *(const char **) spec->ptr = str;
    1748            0 :   return GNUNET_OK;
    1749              : }
    1750              : 
    1751              : 
    1752              : struct GNUNET_JSON_Specification
    1753            0 : TALER_JSON_spec_session_id (const char *field,
    1754              :                             const char **session_id)
    1755              : {
    1756            0 :   struct GNUNET_JSON_Specification ret = {
    1757              :     .parser = &parse_session_id,
    1758              :     .field = field,
    1759              :     .ptr = session_id
    1760              :   };
    1761              : 
    1762            0 :   *session_id = NULL;
    1763            0 :   return ret;
    1764              : }
    1765              : 
    1766              : 
    1767              : /**
    1768              :  * Parse given JSON object to a session ID that must not be empty.
    1769              :  *
    1770              :  * @param cls closure, NULL
    1771              :  * @param root the json object representing data
    1772              :  * @param[out] spec where to write the data
    1773              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1774              :  */
    1775              : static enum GNUNET_GenericReturnValue
    1776            0 : parse_nonempty_session_id (void *cls,
    1777              :                            json_t *root,
    1778              :                            struct GNUNET_JSON_Specification *spec)
    1779              : {
    1780            0 :   if (GNUNET_OK !=
    1781            0 :       parse_session_id (cls,
    1782              :                         root,
    1783              :                         spec))
    1784            0 :     return GNUNET_SYSERR;
    1785            0 :   if ('\0' == (*(const char **) spec->ptr)[0])
    1786              :   {
    1787            0 :     GNUNET_break_op (0);
    1788            0 :     return GNUNET_SYSERR;
    1789              :   }
    1790            0 :   return GNUNET_OK;
    1791              : }
    1792              : 
    1793              : 
    1794              : struct GNUNET_JSON_Specification
    1795            0 : TALER_JSON_spec_nonempty_session_id (const char *field,
    1796              :                                      const char **session_id)
    1797              : {
    1798            0 :   struct GNUNET_JSON_Specification ret = {
    1799              :     .parser = &parse_nonempty_session_id,
    1800              :     .field = field,
    1801              :     .ptr = session_id
    1802              :   };
    1803              : 
    1804            0 :   *session_id = NULL;
    1805            0 :   return ret;
    1806              : }
    1807              : 
    1808              : 
    1809              : /**
    1810              :  * Parse given JSON object to payto:// URI.
    1811              :  *
    1812              :  * @param cls closure, NULL
    1813              :  * @param root the json object representing data
    1814              :  * @param[out] spec where to write the data
    1815              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1816              :  */
    1817              : static enum GNUNET_GenericReturnValue
    1818          768 : parse_full_payto_uri (void *cls,
    1819              :                       json_t *root,
    1820              :                       struct GNUNET_JSON_Specification *spec)
    1821              : {
    1822          768 :   struct TALER_FullPayto *payto_uri = spec->ptr;
    1823              :   const char *str;
    1824              :   char *err;
    1825              : 
    1826              :   (void) cls;
    1827          768 :   str = json_string_value (root);
    1828          768 :   if (NULL == str)
    1829              :   {
    1830            0 :     GNUNET_break_op (0);
    1831            0 :     return GNUNET_SYSERR;
    1832              :   }
    1833          768 :   payto_uri->full_payto = (char *) str;
    1834          768 :   err = TALER_payto_validate (*payto_uri);
    1835          768 :   if (NULL != err)
    1836              :   {
    1837            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1838              :                 "payto:// malformed: %s\n",
    1839              :                 err);
    1840            0 :     GNUNET_free (err);
    1841            0 :     payto_uri->full_payto = NULL;
    1842            0 :     return GNUNET_SYSERR;
    1843              :   }
    1844          768 :   return GNUNET_OK;
    1845              : }
    1846              : 
    1847              : 
    1848              : struct GNUNET_JSON_Specification
    1849          770 : TALER_JSON_spec_full_payto_uri (
    1850              :   const char *field,
    1851              :   struct TALER_FullPayto *payto_uri)
    1852              : {
    1853          770 :   struct GNUNET_JSON_Specification ret = {
    1854              :     .parser = &parse_full_payto_uri,
    1855              :     .field = field,
    1856              :     .ptr = payto_uri
    1857              :   };
    1858              : 
    1859          770 :   payto_uri->full_payto = NULL;
    1860          770 :   return ret;
    1861              : }
    1862              : 
    1863              : 
    1864              : /**
    1865              :  * Parse given JSON object to payto:// URI.
    1866              :  *
    1867              :  * @param cls closure, NULL
    1868              :  * @param root the json object representing data
    1869              :  * @param[out] spec where to write the data
    1870              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1871              :  */
    1872              : static enum GNUNET_GenericReturnValue
    1873            6 : parse_normalized_payto_uri (void *cls,
    1874              :                             json_t *root,
    1875              :                             struct GNUNET_JSON_Specification *spec)
    1876              : {
    1877            6 :   struct TALER_NormalizedPayto *payto_uri = spec->ptr;
    1878              :   const char *str;
    1879              : 
    1880              :   (void) cls;
    1881            6 :   str = json_string_value (root);
    1882            6 :   if (NULL == str)
    1883              :   {
    1884            0 :     GNUNET_break_op (0);
    1885            0 :     return GNUNET_SYSERR;
    1886              :   }
    1887            6 :   payto_uri->normalized_payto = (char *) str;
    1888              :   {
    1889              :     char *err;
    1890              : 
    1891            6 :     err = TALER_normalized_payto_validate (*payto_uri);
    1892            6 :     if (NULL != err)
    1893              :     {
    1894            0 :       GNUNET_break_op (0);
    1895            0 :       GNUNET_free (err);
    1896            0 :       payto_uri->normalized_payto = NULL;
    1897            0 :       return GNUNET_SYSERR;
    1898              :     }
    1899              :   }
    1900            6 :   return GNUNET_OK;
    1901              : }
    1902              : 
    1903              : 
    1904              : struct GNUNET_JSON_Specification
    1905            6 : TALER_JSON_spec_normalized_payto_uri (
    1906              :   const char *field,
    1907              :   struct TALER_NormalizedPayto *payto_uri)
    1908              : {
    1909            6 :   struct GNUNET_JSON_Specification ret = {
    1910              :     .parser = &parse_normalized_payto_uri,
    1911              :     .field = field,
    1912              :     .ptr = payto_uri
    1913              :   };
    1914              : 
    1915            6 :   payto_uri->normalized_payto = NULL;
    1916            6 :   return ret;
    1917              : }
    1918              : 
    1919              : 
    1920              : /**
    1921              :  * Parse given JSON object with protocol version.
    1922              :  *
    1923              :  * @param cls closure, NULL
    1924              :  * @param root the json object representing data
    1925              :  * @param[out] spec where to write the data
    1926              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1927              :  */
    1928              : static enum GNUNET_GenericReturnValue
    1929           47 : parse_protocol_version (void *cls,
    1930              :                         json_t *root,
    1931              :                         struct GNUNET_JSON_Specification *spec)
    1932              : {
    1933           47 :   struct TALER_JSON_ProtocolVersion *pv = spec->ptr;
    1934              :   const char *ver;
    1935              :   char dummy;
    1936              : 
    1937              :   (void) cls;
    1938           47 :   if (! json_is_string (root))
    1939              :   {
    1940            0 :     GNUNET_break_op (0);
    1941            0 :     return GNUNET_SYSERR;
    1942              :   }
    1943           47 :   ver = json_string_value (root);
    1944           47 :   if (3 != sscanf (ver,
    1945              :                    "%u:%u:%u%c",
    1946              :                    &pv->current,
    1947              :                    &pv->revision,
    1948              :                    &pv->age,
    1949              :                    &dummy))
    1950              :   {
    1951            0 :     GNUNET_break_op (0);
    1952            0 :     return GNUNET_SYSERR;
    1953              :   }
    1954           47 :   return GNUNET_OK;
    1955              : }
    1956              : 
    1957              : 
    1958              : struct GNUNET_JSON_Specification
    1959           47 : TALER_JSON_spec_version (const char *field,
    1960              :                          struct TALER_JSON_ProtocolVersion *ver)
    1961              : {
    1962           47 :   struct GNUNET_JSON_Specification ret = {
    1963              :     .parser = &parse_protocol_version,
    1964              :     .field = field,
    1965              :     .ptr = ver
    1966              :   };
    1967              : 
    1968           47 :   return ret;
    1969              : }
    1970              : 
    1971              : 
    1972              : /**
    1973              :  * Parse given JSON object to an OTP key.
    1974              :  *
    1975              :  * @param cls closure, NULL
    1976              :  * @param root the json object representing data
    1977              :  * @param[out] spec where to write the data
    1978              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1979              :  */
    1980              : static enum GNUNET_GenericReturnValue
    1981            0 : parse_otp_key (void *cls,
    1982              :                json_t *root,
    1983              :                struct GNUNET_JSON_Specification *spec)
    1984              : {
    1985              :   const char *pos_key;
    1986              : 
    1987              :   (void) cls;
    1988            0 :   pos_key = json_string_value (root);
    1989            0 :   if (NULL == pos_key)
    1990              :   {
    1991            0 :     GNUNET_break_op (0);
    1992            0 :     return GNUNET_SYSERR;
    1993              :   }
    1994              :   {
    1995            0 :     size_t pos_key_length = strlen (pos_key);
    1996              :     void *key; /* pos_key in binary */
    1997              :     size_t key_len; /* length of the key */
    1998              :     int dret;
    1999              : 
    2000            0 :     key_len = pos_key_length * 5 / 8;
    2001            0 :     key = GNUNET_malloc (key_len);
    2002            0 :     dret = TALER_rfc3548_base32decode (pos_key,
    2003              :                                        pos_key_length,
    2004              :                                        key,
    2005              :                                        key_len);
    2006            0 :     if (-1 == dret)
    2007              :     {
    2008            0 :       GNUNET_free (key);
    2009            0 :       GNUNET_break_op (0);
    2010            0 :       return GNUNET_SYSERR;
    2011              :     }
    2012            0 :     GNUNET_free (key);
    2013              :   }
    2014            0 :   *(const char **) spec->ptr = pos_key;
    2015            0 :   return GNUNET_OK;
    2016              : }
    2017              : 
    2018              : 
    2019              : struct GNUNET_JSON_Specification
    2020            0 : TALER_JSON_spec_otp_key (const char *name,
    2021              :                          const char **otp_key)
    2022              : {
    2023            0 :   struct GNUNET_JSON_Specification ret = {
    2024              :     .parser = &parse_otp_key,
    2025              :     .field = name,
    2026              :     .ptr = otp_key
    2027              :   };
    2028              : 
    2029            0 :   *otp_key = NULL;
    2030            0 :   return ret;
    2031              : }
    2032              : 
    2033              : 
    2034              : /**
    2035              :  * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm`
    2036              :  *
    2037              :  * @param cls closure, NULL
    2038              :  * @param root the json object representing data
    2039              :  * @param[out] spec where to write the data
    2040              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    2041              :  */
    2042              : static enum GNUNET_GenericReturnValue
    2043            0 : parse_otp_type (void *cls,
    2044              :                 json_t *root,
    2045              :                 struct GNUNET_JSON_Specification *spec)
    2046              : {
    2047              :   static const struct Entry
    2048              :   {
    2049              :     const char *name;
    2050              :     enum TALER_MerchantConfirmationAlgorithm val;
    2051              :   } lt [] = {
    2052              :     { .name = "NONE",
    2053              :       .val = TALER_MCA_NONE },
    2054              :     { .name = "TOTP_WITHOUT_PRICE",
    2055              :       .val = TALER_MCA_WITHOUT_PRICE },
    2056              :     { .name = "TOTP_WITH_PRICE",
    2057              :       .val = TALER_MCA_WITH_PRICE },
    2058              :     { .name = "ECDSA_CHALLENGE",
    2059              :       .val = TALER_MCA_ECDSA_CHALLENGE },
    2060              :     { .name = "EDDSA_CHALLENGE",
    2061              :       .val = TALER_MCA_EDDSA_CHALLENGE },
    2062              :     { .name = NULL,
    2063              :       .val = TALER_MCA_NONE },
    2064              :   };
    2065            0 :   enum TALER_MerchantConfirmationAlgorithm *res
    2066              :     = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr;
    2067              : 
    2068              :   (void) cls;
    2069            0 :   if (json_is_string (root))
    2070              :   {
    2071              :     const char *str;
    2072              : 
    2073            0 :     str = json_string_value (root);
    2074            0 :     if (NULL == str)
    2075              :     {
    2076            0 :       GNUNET_break_op (0);
    2077            0 :       return GNUNET_SYSERR;
    2078              :     }
    2079            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    2080              :     {
    2081            0 :       if (0 == strcasecmp (str,
    2082            0 :                            lt[i].name))
    2083              :       {
    2084            0 :         *res = lt[i].val;
    2085            0 :         return GNUNET_OK;
    2086              :       }
    2087              :     }
    2088            0 :     GNUNET_break_op (0);
    2089              :   }
    2090            0 :   if (json_is_integer (root))
    2091              :   {
    2092              :     json_int_t val;
    2093              : 
    2094            0 :     val = json_integer_value (root);
    2095            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    2096              :     {
    2097            0 :       if (val == lt[i].val)
    2098              :       {
    2099            0 :         *res = lt[i].val;
    2100            0 :         return GNUNET_OK;
    2101              :       }
    2102              :     }
    2103            0 :     GNUNET_break_op (0);
    2104            0 :     return GNUNET_SYSERR;
    2105              :   }
    2106            0 :   GNUNET_break_op (0);
    2107            0 :   return GNUNET_SYSERR;
    2108              : }
    2109              : 
    2110              : 
    2111              : struct GNUNET_JSON_Specification
    2112            0 : TALER_JSON_spec_otp_type (const char *name,
    2113              :                           enum TALER_MerchantConfirmationAlgorithm *mca)
    2114              : {
    2115            0 :   struct GNUNET_JSON_Specification ret = {
    2116              :     .parser = &parse_otp_type,
    2117              :     .field = name,
    2118              :     .ptr = mca
    2119              :   };
    2120              : 
    2121            0 :   *mca = TALER_MCA_NONE;
    2122            0 :   return ret;
    2123              : }
    2124              : 
    2125              : 
    2126              : /**
    2127              :  * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent`
    2128              :  *
    2129              :  * @param cls closure, NULL
    2130              :  * @param root the json object representing data
    2131              :  * @param[out] spec where to write the data
    2132              :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    2133              :  */
    2134              : static enum GNUNET_GenericReturnValue
    2135          334 : parse_kycte (void *cls,
    2136              :              json_t *root,
    2137              :              struct GNUNET_JSON_Specification *spec)
    2138              : {
    2139              :   static const struct Entry
    2140              :   {
    2141              :     const char *name;
    2142              :     enum TALER_KYCLOGIC_KycTriggerEvent val;
    2143              :   } lt [] = {
    2144              :     { .name = "NONE",
    2145              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
    2146              :     { .name = "WITHDRAW",
    2147              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
    2148              :     { .name = "DEPOSIT",
    2149              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
    2150              :     { .name = "MERGE",
    2151              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
    2152              :     { .name = "BALANCE",
    2153              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
    2154              :     { .name = "CLOSE",
    2155              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
    2156              :     { .name = "AGGREGATE",
    2157              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
    2158              :     { .name = "TRANSACTION",
    2159              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
    2160              :     { .name = "REFUND",
    2161              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
    2162              :     { .name = NULL,
    2163              :       .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
    2164              :   };
    2165          334 :   enum TALER_KYCLOGIC_KycTriggerEvent *res
    2166              :     = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr;
    2167              : 
    2168              :   (void) cls;
    2169          334 :   if (json_is_string (root))
    2170              :   {
    2171              :     const char *str;
    2172              : 
    2173          334 :     str = json_string_value (root);
    2174          334 :     if (NULL == str)
    2175              :     {
    2176            0 :       GNUNET_break_op (0);
    2177            0 :       return GNUNET_SYSERR;
    2178              :     }
    2179         1545 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    2180              :     {
    2181         1545 :       if (0 == strcasecmp (str,
    2182         1545 :                            lt[i].name))
    2183              :       {
    2184          334 :         *res = lt[i].val;
    2185          334 :         return GNUNET_OK;
    2186              :       }
    2187              :     }
    2188            0 :     GNUNET_break_op (0);
    2189            0 :     return GNUNET_SYSERR;
    2190              :   }
    2191            0 :   if (json_is_integer (root))
    2192              :   {
    2193              :     json_int_t val;
    2194              : 
    2195            0 :     val = json_integer_value (root);
    2196            0 :     for (unsigned int i = 0; NULL != lt[i].name; i++)
    2197              :     {
    2198            0 :       if (val == lt[i].val)
    2199              :       {
    2200            0 :         *res = lt[i].val;
    2201            0 :         return GNUNET_OK;
    2202              :       }
    2203              :     }
    2204            0 :     GNUNET_break_op (0);
    2205            0 :     return GNUNET_SYSERR;
    2206              :   }
    2207            0 :   GNUNET_break_op (0);
    2208            0 :   return GNUNET_SYSERR;
    2209              : }
    2210              : 
    2211              : 
    2212              : struct GNUNET_JSON_Specification
    2213          335 : TALER_JSON_spec_kycte (const char *name,
    2214              :                        enum TALER_KYCLOGIC_KycTriggerEvent *kte)
    2215              : {
    2216          335 :   struct GNUNET_JSON_Specification ret = {
    2217              :     .parser = &parse_kycte,
    2218              :     .field = name,
    2219              :     .ptr = kte
    2220              :   };
    2221              : 
    2222          335 :   *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE;
    2223          335 :   return ret;
    2224              : }
    2225              : 
    2226              : 
    2227              : /**
    2228              :  * Parser combinator of a tuple of parsers, for parsing
    2229              :  * an array of expected size and element types.
    2230              :  *
    2231              :  * @param cls closure, array of specs, NULL terminated
    2232              :  * @param root the json root
    2233              :  * @param[out] spec where to write the data
    2234              :  */
    2235              : static enum GNUNET_GenericReturnValue
    2236          115 : parse_tuple_of (void *cls,
    2237              :                 json_t *root,
    2238              :                 struct GNUNET_JSON_Specification *spec)
    2239              : {
    2240          115 :   struct GNUNET_JSON_Specification *specs = cls;
    2241              :   static size_t max_specs = 100;
    2242          115 :   bool found_end = false;
    2243              : 
    2244              :   enum GNUNET_GenericReturnValue ret;
    2245              : 
    2246          115 :   if (! json_is_array (root))
    2247              :   {
    2248            0 :     return GNUNET_SYSERR;
    2249              :   }
    2250              : 
    2251              :   {
    2252              :     size_t num;
    2253          345 :     for (num = 0; num< max_specs; num++)
    2254              :     {
    2255          345 :       if (NULL == specs[num].parser)
    2256              :       {
    2257          115 :         found_end = true;
    2258          115 :         break;
    2259              :       }
    2260              :     }
    2261          115 :     GNUNET_assert (found_end);
    2262              : 
    2263          115 :     if (num != json_array_size (root))
    2264              :     {
    2265            0 :       GNUNET_break_op (0);
    2266            0 :       return GNUNET_SYSERR;
    2267              :     }
    2268              :   }
    2269              : 
    2270              :   {
    2271              :     json_t *j_entry;
    2272              :     size_t idx;
    2273              : 
    2274          345 :     json_array_foreach (root, idx, j_entry) {
    2275          230 :       ret = GNUNET_JSON_parse (j_entry,
    2276          230 :                                &specs[idx],
    2277              :                                NULL,
    2278              :                                NULL);
    2279          230 :       if (GNUNET_OK != ret)
    2280              :       {
    2281            0 :         GNUNET_break_op (0);
    2282            0 :         return GNUNET_SYSERR;
    2283              :       }
    2284              :     }
    2285              :   }
    2286              : 
    2287          115 :   return GNUNET_OK;
    2288              : }
    2289              : 
    2290              : 
    2291              : struct GNUNET_JSON_Specification
    2292          129 : TALER_JSON_spec_tuple_of (
    2293              :   const char *field,
    2294              :   struct GNUNET_JSON_Specification specs[])
    2295              : {
    2296          129 :   struct GNUNET_JSON_Specification ret = {
    2297              :     .parser = &parse_tuple_of,
    2298              :     .field = field,
    2299              :     .cls = specs
    2300              :   };
    2301              : 
    2302          129 :   return ret;
    2303              : }
    2304              : 
    2305              : 
    2306              : /**
    2307              :  * Parser for an array of unknown length but
    2308              :  * of elements of the same type with the same
    2309              :  * fixed length.
    2310              :  *
    2311              :  * @param cls closure, entry_size
    2312              :  * @param root the json root
    2313              :  * @param spec the output spec
    2314              :  */
    2315              : static enum GNUNET_GenericReturnValue
    2316           90 : parse_array_fixed (void *cls,
    2317              :                    json_t *root,
    2318              :                    struct GNUNET_JSON_Specification *spec)
    2319              : {
    2320              :   enum GNUNET_GenericReturnValue ret;
    2321           90 :   size_t entry_size = (size_t) cls;
    2322              :   size_t num_entries;
    2323              : 
    2324           90 :   GNUNET_assert (0< entry_size);
    2325           90 :   num_entries = spec->ptr_size / entry_size;
    2326           90 :   GNUNET_assert (0 < num_entries);
    2327              : 
    2328              : 
    2329           90 :   if (! json_is_array (root))
    2330              :   {
    2331            0 :     GNUNET_break_op (0);
    2332            0 :     return GNUNET_SYSERR;
    2333              :   }
    2334           90 :   if (num_entries != json_array_size (root))
    2335              :   {
    2336            0 :     GNUNET_break_op (0);
    2337            0 :     return GNUNET_SYSERR;
    2338              :   }
    2339              : 
    2340              :   {
    2341              :     json_t *j_entry;
    2342              :     size_t idx;
    2343           90 :     void *ptr = spec->ptr;
    2344           90 :     void *end = spec->ptr + spec->ptr_size;
    2345              : 
    2346          450 :     json_array_foreach (root, idx, j_entry) {
    2347              :       struct GNUNET_JSON_Specification esp[] = {
    2348          360 :         GNUNET_JSON_spec_fixed (NULL,
    2349              :                                 ptr,
    2350              :                                 entry_size),
    2351          360 :         GNUNET_JSON_spec_end ()
    2352              :       };
    2353          360 :       GNUNET_assert (ptr < end);
    2354          360 :       ret = GNUNET_JSON_parse (j_entry,
    2355              :                                esp,
    2356              :                                NULL,
    2357              :                                NULL);
    2358          360 :       if (GNUNET_OK != ret)
    2359              :       {
    2360            0 :         GNUNET_break_op (0);
    2361            0 :         return GNUNET_SYSERR;
    2362              :       }
    2363          360 :       ptr += entry_size;
    2364              :     }
    2365              :   }
    2366           90 :   return GNUNET_OK;
    2367              : }
    2368              : 
    2369              : 
    2370              : struct GNUNET_JSON_Specification
    2371           90 : TALER_JSON_spec_array_fixed (
    2372              :   const char *field,
    2373              :   size_t num_entries,
    2374              :   void *entries,
    2375              :   size_t entry_size)
    2376              : {
    2377           90 :   struct GNUNET_JSON_Specification ret = {
    2378              :     .parser = &parse_array_fixed,
    2379              :     .ptr = entries,
    2380           90 :     .ptr_size = entry_size * num_entries,
    2381              :     .field = field,
    2382           90 :     .cls = (void *) entry_size,
    2383              :   };
    2384              : 
    2385           90 :   GNUNET_assert ((num_entries <= 1) ||
    2386              :                  (entry_size * num_entries > entry_size));
    2387           90 :   return ret;
    2388              : }
    2389              : 
    2390              : 
    2391              : /**
    2392              :  * Closure for the parser of arrays of fixed size data
    2393              :  * of unknown array length
    2394              :  */
    2395              : struct closure_array_of_data
    2396              : {
    2397              :   /**
    2398              :    * Fixed (known) size per entry
    2399              :    */
    2400              :   size_t entry_size;
    2401              : 
    2402              :   /**
    2403              :    * Pointer where to put the number of elements
    2404              :    * allocated, i.e. the number of elements in the
    2405              :    * json array.
    2406              :    */
    2407              :   size_t *num_entries;
    2408              : };
    2409              : 
    2410              : /**
    2411              :  * Parser for an array of data of known element size,
    2412              :  * but unknown array length
    2413              :  */
    2414              : static enum GNUNET_GenericReturnValue
    2415            8 : parse_array_of_data (void *cls,
    2416              :                      json_t *root,
    2417              :                      struct GNUNET_JSON_Specification *spec)
    2418              : {
    2419              :   enum GNUNET_GenericReturnValue ret;
    2420            8 :   struct closure_array_of_data *info = cls;
    2421              :   size_t num_entries;
    2422              : 
    2423            8 :   if (! json_is_array (root))
    2424              :   {
    2425            0 :     GNUNET_break_op (0);
    2426            0 :     return GNUNET_SYSERR;
    2427              :   }
    2428            8 :   num_entries = json_array_size (root);
    2429            8 :   *info->num_entries = num_entries;
    2430            8 :   if (0 == num_entries)
    2431              :   {
    2432            0 :     *(char **) spec->ptr = NULL;
    2433            0 :     return GNUNET_OK;
    2434              :   }
    2435              : 
    2436            8 :   spec->ptr_size = num_entries * info->entry_size;
    2437            8 :   GNUNET_assert (spec->ptr_size > num_entries);
    2438            8 :   *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size);
    2439              : 
    2440              :   {
    2441              :     json_t *j_entry;
    2442              :     size_t idx;
    2443            8 :     char *ptr = *(char **) spec->ptr;
    2444            8 :     char *end = ptr + spec->ptr_size;
    2445              : 
    2446           25 :     json_array_foreach (root, idx, j_entry) {
    2447              :       struct GNUNET_JSON_Specification esp[] = {
    2448           17 :         GNUNET_JSON_spec_fixed (NULL,
    2449              :                                 ptr,
    2450              :                                 info->entry_size),
    2451           17 :         GNUNET_JSON_spec_end ()
    2452              :       };
    2453           17 :       GNUNET_assert (ptr < end);
    2454           17 :       ret = GNUNET_JSON_parse (j_entry,
    2455              :                                esp,
    2456              :                                NULL,
    2457              :                                NULL);
    2458           17 :       if (GNUNET_OK != ret)
    2459              :       {
    2460            0 :         GNUNET_break_op (0);
    2461            0 :         return GNUNET_SYSERR;
    2462              :       }
    2463           17 :       ptr += info->entry_size;
    2464              :     }
    2465              :   }
    2466            8 :   return GNUNET_OK;
    2467              : }
    2468              : 
    2469              : 
    2470              : /**
    2471              :  * Cleanup data left from parsing an array of fixed size (but unknown length).
    2472              :  *
    2473              :  * @param cls closure_of_array_data
    2474              :  * @param[out] spec where to free the data
    2475              :  */
    2476              : static void
    2477            7 : cleaner_array_of_data (void *cls,
    2478              :                        struct GNUNET_JSON_Specification *spec)
    2479              : {
    2480            7 :   struct closure_array_of_data *info = cls;
    2481              : 
    2482            7 :   GNUNET_free (*(void **) spec->ptr);
    2483            7 :   GNUNET_free (info);
    2484            7 : }
    2485              : 
    2486              : 
    2487              : struct GNUNET_JSON_Specification
    2488            8 : TALER_JSON_spec_array_of_data (
    2489              :   const char *field,
    2490              :   size_t entry_size,
    2491              :   size_t *num_entries,
    2492              :   void **entries)
    2493              : {
    2494              :   struct closure_array_of_data *cls;
    2495              : 
    2496            8 :   GNUNET_assert (0< entry_size);
    2497            8 :   *entries = NULL;
    2498            8 :   *num_entries = 0;
    2499            8 :   cls = GNUNET_new (struct closure_array_of_data);
    2500            8 :   cls->num_entries = num_entries;
    2501            8 :   cls->entry_size = entry_size;
    2502              :   {
    2503            8 :     struct GNUNET_JSON_Specification ret = {
    2504              :       .parser = &parse_array_of_data,
    2505              :       .ptr = entries,
    2506              :       .field = field,
    2507              :       .cleaner = &cleaner_array_of_data,
    2508              :       .cls = (void *) cls,
    2509              :     };
    2510              : 
    2511            8 :     return ret;
    2512              :   }
    2513              : }
    2514              : 
    2515              : 
    2516              : struct GNUNET_JSON_Specification
    2517            7 : TALER_JSON_spec_array_of_denom_pub_h (
    2518              :   const char *field,
    2519              :   size_t *num_entries,
    2520              :   struct TALER_DenominationHashP **entries)
    2521              : {
    2522            7 :   *num_entries = 0;
    2523            7 :   *entries = NULL;
    2524            7 :   return TALER_JSON_spec_array_of_data (
    2525              :     field,
    2526              :     sizeof (struct TALER_DenominationHashP),
    2527              :     num_entries,
    2528              :     (void **) entries);
    2529              : }
    2530              : 
    2531              : 
    2532              : /**
    2533              :  * Parser for an array of blinded denomination signatures,
    2534              :  * of unknown array length
    2535              :  */
    2536              : static enum GNUNET_GenericReturnValue
    2537           14 : parse_array_of_blinded_denom_sigs (void *cls,
    2538              :                                    json_t *root,
    2539              :                                    struct GNUNET_JSON_Specification *spec)
    2540              : {
    2541              :   enum GNUNET_GenericReturnValue ret;
    2542           14 :   struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
    2543           14 :   size_t expected_num_entries = (size_t) cls;
    2544              :   size_t num_entries;
    2545              : 
    2546           14 :   if (! json_is_array (root))
    2547              :   {
    2548            0 :     GNUNET_break_op (0);
    2549            0 :     return GNUNET_SYSERR;
    2550              :   }
    2551           14 :   num_entries = json_array_size (root);
    2552           14 :   if (num_entries != expected_num_entries)
    2553              :   {
    2554            0 :     GNUNET_break_op (0);
    2555            0 :     return GNUNET_SYSERR;
    2556              :   }
    2557              : 
    2558              :   {
    2559              :     json_t *j_entry;
    2560              :     size_t idx;
    2561           14 :     struct TALER_BlindedDenominationSignature *ptr = sigs;
    2562              : 
    2563           70 :     json_array_foreach (root, idx, j_entry) {
    2564              :       struct GNUNET_JSON_Specification esp[] = {
    2565           56 :         TALER_JSON_spec_blinded_denom_sig (NULL,
    2566              :                                            ptr),
    2567           56 :         GNUNET_JSON_spec_end ()
    2568              :       };
    2569           56 :       ret = GNUNET_JSON_parse (j_entry,
    2570              :                                esp,
    2571              :                                NULL,
    2572              :                                NULL);
    2573           56 :       if (GNUNET_OK != ret)
    2574              :       {
    2575            0 :         GNUNET_break_op (0);
    2576            0 :         for (size_t i = 0; i < idx; i++)
    2577              :         {
    2578            0 :           TALER_blinded_denom_sig_free (&sigs[i]);
    2579            0 :           sigs[i].blinded_sig = NULL;
    2580              :         }
    2581            0 :         return GNUNET_SYSERR;
    2582              :       }
    2583           56 :       ptr++;
    2584              :     }
    2585              :   }
    2586           14 :   return GNUNET_OK;
    2587              : }
    2588              : 
    2589              : 
    2590              : /**
    2591              :  * Cleanup data left from parsing an array of blinded signatures.
    2592              :  *
    2593              :  * @param cls pointer to a size_t with the length of the array
    2594              :  * @param[out] spec where to free the data
    2595              :  */
    2596              : static void
    2597           14 : cleaner_array_of_blinded_denom_sigs (
    2598              :   void *cls,
    2599              :   struct GNUNET_JSON_Specification *spec)
    2600              : {
    2601           14 :   struct TALER_BlindedDenominationSignature *sigs = spec->ptr;
    2602           14 :   size_t num_entries = (size_t) cls;
    2603              : 
    2604           70 :   for (size_t i = 0; i < num_entries; i++)
    2605              :   {
    2606           56 :     if (NULL != sigs[i].blinded_sig)
    2607              :     {
    2608           56 :       TALER_blinded_denom_sig_free (&sigs[i]);
    2609           56 :       sigs[i].blinded_sig = NULL;
    2610              :     }
    2611              :   }
    2612           14 : }
    2613              : 
    2614              : 
    2615              : struct GNUNET_JSON_Specification
    2616           14 : TALER_JSON_spec_array_of_blinded_denom_sigs (
    2617              :   const char *field,
    2618              :   size_t num_entries,
    2619              :   struct TALER_BlindedDenominationSignature *entries)
    2620              : {
    2621           14 :   struct GNUNET_JSON_Specification ret = {
    2622              :     .parser = &parse_array_of_blinded_denom_sigs,
    2623              :     .ptr = entries,
    2624              :     .field = field,
    2625              :     .cleaner = &cleaner_array_of_blinded_denom_sigs,
    2626           14 :     .cls = (void *) num_entries,
    2627              :   };
    2628              : 
    2629           70 :   for (size_t i = 0; i<num_entries; i++)
    2630           56 :     entries[i].blinded_sig = NULL;
    2631           14 :   return ret;
    2632              : }
    2633              : 
    2634              : 
    2635              : /* end of json/json_helper.c */
        

Generated by: LCOV version 2.0-1