LCOV - code coverage report
Current view: top level - json - json_helper.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 23 408 5.6 %
Date: 2022-08-25 06:15:09 Functions: 4 37 10.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2021 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 "platform.h"
      24             : #include <gnunet/gnunet_util_lib.h>
      25             : #include "taler_util.h"
      26             : #include "taler_json_lib.h"
      27             : 
      28             : 
      29             : /**
      30             :  * Convert string value to numeric cipher value.
      31             :  *
      32             :  * @param cipher_s input string
      33             :  * @return numeric cipher value
      34             :  */
      35             : static enum TALER_DenominationCipher
      36           0 : string_to_cipher (const char *cipher_s)
      37             : {
      38           0 :   if ((0 == strcasecmp (cipher_s,
      39           0 :                         "RSA")) ||
      40           0 :       (0 == strcasecmp (cipher_s,
      41             :                         "RSA+age_restricted")))
      42           0 :     return TALER_DENOMINATION_RSA;
      43           0 :   if ((0 == strcasecmp (cipher_s,
      44           0 :                         "CS")) ||
      45           0 :       (0 == strcasecmp (cipher_s,
      46             :                         "CS+age_restricted")))
      47           0 :     return TALER_DENOMINATION_CS;
      48           0 :   return TALER_DENOMINATION_INVALID;
      49             : }
      50             : 
      51             : 
      52             : json_t *
      53          17 : TALER_JSON_from_amount (const struct TALER_Amount *amount)
      54             : {
      55          17 :   char *amount_str = TALER_amount_to_string (amount);
      56             : 
      57          17 :   GNUNET_assert (NULL != amount_str);
      58             :   {
      59          17 :     json_t *j = json_string (amount_str);
      60             : 
      61          17 :     GNUNET_free (amount_str);
      62          17 :     return j;
      63             :   }
      64             : }
      65             : 
      66             : 
      67             : json_t *
      68           0 : TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO *amount)
      69             : {
      70             :   struct TALER_Amount a;
      71             : 
      72           0 :   TALER_amount_ntoh (&a,
      73             :                      amount);
      74           0 :   return TALER_JSON_from_amount (&a);
      75             : }
      76             : 
      77             : 
      78             : /**
      79             :  * Parse given JSON object to Amount
      80             :  *
      81             :  * @param cls closure, expected currency, or NULL
      82             :  * @param root the json object representing data
      83             :  * @param[out] spec where to write the data
      84             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
      85             :  */
      86             : static enum GNUNET_GenericReturnValue
      87          15 : parse_amount (void *cls,
      88             :               json_t *root,
      89             :               struct GNUNET_JSON_Specification *spec)
      90             : {
      91          15 :   const char *currency = cls;
      92          15 :   struct TALER_Amount *r_amount = spec->ptr;
      93             : 
      94             :   (void) cls;
      95          15 :   if (! json_is_string (root))
      96             :   {
      97           0 :     GNUNET_break_op (0);
      98           0 :     return GNUNET_SYSERR;
      99             :   }
     100          15 :   if (GNUNET_OK !=
     101          15 :       TALER_string_to_amount (json_string_value (root),
     102             :                               r_amount))
     103             :   {
     104           0 :     GNUNET_break_op (0);
     105           0 :     return GNUNET_SYSERR;
     106             :   }
     107          15 :   if ( (NULL != currency) &&
     108             :        (0 !=
     109           9 :         strcasecmp (currency,
     110           9 :                     r_amount->currency)) )
     111             :   {
     112           0 :     GNUNET_break_op (0);
     113           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     114             :                 "Expected currency `%s', but amount used currency `%s' in field `%s'\n",
     115             :                 currency,
     116             :                 r_amount->currency,
     117             :                 spec->field);
     118           0 :     return GNUNET_SYSERR;
     119             :   }
     120          15 :   return GNUNET_OK;
     121             : }
     122             : 
     123             : 
     124             : struct GNUNET_JSON_Specification
     125           9 : TALER_JSON_spec_amount (const char *name,
     126             :                         const char *currency,
     127             :                         struct TALER_Amount *r_amount)
     128             : {
     129           9 :   struct GNUNET_JSON_Specification ret = {
     130             :     .parser = &parse_amount,
     131             :     .cleaner = NULL,
     132             :     .cls = (void *) currency,
     133             :     .field = name,
     134             :     .ptr = r_amount,
     135             :     .ptr_size = 0,
     136             :     .size_ptr = NULL
     137             :   };
     138             : 
     139           9 :   GNUNET_assert (NULL != currency);
     140           9 :   return ret;
     141             : }
     142             : 
     143             : 
     144             : struct GNUNET_JSON_Specification
     145           6 : TALER_JSON_spec_amount_any (const char *name,
     146             :                             struct TALER_Amount *r_amount)
     147             : {
     148           6 :   struct GNUNET_JSON_Specification ret = {
     149             :     .parser = &parse_amount,
     150             :     .cleaner = NULL,
     151             :     .cls = NULL,
     152             :     .field = name,
     153             :     .ptr = r_amount,
     154             :     .ptr_size = 0,
     155             :     .size_ptr = NULL
     156             :   };
     157             : 
     158           6 :   return ret;
     159             : }
     160             : 
     161             : 
     162             : /**
     163             :  * Parse given JSON object to Amount in NBO.
     164             :  *
     165             :  * @param cls closure, NULL
     166             :  * @param root the json object representing data
     167             :  * @param[out] spec where to write the data
     168             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     169             :  */
     170             : static enum GNUNET_GenericReturnValue
     171           0 : parse_amount_nbo (void *cls,
     172             :                   json_t *root,
     173             :                   struct GNUNET_JSON_Specification *spec)
     174             : {
     175           0 :   const char *currency = cls;
     176           0 :   struct TALER_AmountNBO *r_amount = spec->ptr;
     177             :   const char *sv;
     178             : 
     179             :   (void) cls;
     180           0 :   if (! json_is_string (root))
     181             :   {
     182           0 :     GNUNET_break (0);
     183           0 :     return GNUNET_SYSERR;
     184             :   }
     185           0 :   sv = json_string_value (root);
     186           0 :   if (GNUNET_OK !=
     187           0 :       TALER_string_to_amount_nbo (sv,
     188             :                                   r_amount))
     189             :   {
     190           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     191             :                 "`%s' is not a valid amount\n",
     192             :                 sv);
     193           0 :     GNUNET_break_op (0);
     194           0 :     return GNUNET_SYSERR;
     195             :   }
     196           0 :   if ( (NULL != currency) &&
     197             :        (0 !=
     198           0 :         strcasecmp (currency,
     199           0 :                     r_amount->currency)) )
     200             :   {
     201           0 :     GNUNET_break_op (0);
     202           0 :     return GNUNET_SYSERR;
     203             :   }
     204           0 :   return GNUNET_OK;
     205             : }
     206             : 
     207             : 
     208             : struct GNUNET_JSON_Specification
     209           0 : TALER_JSON_spec_amount_nbo (const char *name,
     210             :                             const char *currency,
     211             :                             struct TALER_AmountNBO *r_amount)
     212             : {
     213           0 :   struct GNUNET_JSON_Specification ret = {
     214             :     .parser = &parse_amount_nbo,
     215             :     .cleaner = NULL,
     216             :     .cls = (void *) currency,
     217             :     .field = name,
     218             :     .ptr = r_amount,
     219             :     .ptr_size = 0,
     220             :     .size_ptr = NULL
     221             :   };
     222             : 
     223           0 :   GNUNET_assert (NULL != currency);
     224           0 :   return ret;
     225             : }
     226             : 
     227             : 
     228             : struct GNUNET_JSON_Specification
     229           0 : TALER_JSON_spec_amount_any_nbo (const char *name,
     230             :                                 struct TALER_AmountNBO *r_amount)
     231             : {
     232           0 :   struct GNUNET_JSON_Specification ret = {
     233             :     .parser = &parse_amount_nbo,
     234             :     .cleaner = NULL,
     235             :     .cls = NULL,
     236             :     .field = name,
     237             :     .ptr = r_amount,
     238             :     .ptr_size = 0,
     239             :     .size_ptr = NULL
     240             :   };
     241             : 
     242           0 :   return ret;
     243             : }
     244             : 
     245             : 
     246             : static enum GNUNET_GenericReturnValue
     247           0 : parse_denomination_group (void *cls,
     248             :                           json_t *root,
     249             :                           struct GNUNET_JSON_Specification *spec)
     250             : {
     251           0 :   struct TALER_DenominationGroup *group = spec->ptr;
     252             :   const char *cipher;
     253           0 :   const char *currency = cls;
     254           0 :   bool age_mask_missing = false;
     255           0 :   bool has_age_restricted_suffix = false;
     256             :   struct GNUNET_JSON_Specification gspec[] = {
     257           0 :     GNUNET_JSON_spec_string ("cipher",
     258             :                              &cipher),
     259           0 :     TALER_JSON_spec_amount ("value",
     260             :                             currency,
     261             :                             &group->value),
     262           0 :     TALER_JSON_SPEC_DENOM_FEES ("fee",
     263             :                                 currency,
     264             :                                 &group->fees),
     265           0 :     GNUNET_JSON_spec_mark_optional (
     266             :       GNUNET_JSON_spec_uint32 ("age_mask",
     267             :                                &group->age_mask.bits),
     268             :       &age_mask_missing),
     269           0 :     GNUNET_JSON_spec_fixed_auto ("hash",
     270             :                                  &group->hash),
     271           0 :     GNUNET_JSON_spec_end ()
     272             :   };
     273             :   const char *emsg;
     274             :   unsigned int eline;
     275             : 
     276           0 :   if (GNUNET_OK !=
     277           0 :       GNUNET_JSON_parse (root,
     278             :                          gspec,
     279             :                          &emsg,
     280             :                          &eline))
     281             :   {
     282           0 :     GNUNET_break_op (0);
     283           0 :     return GNUNET_SYSERR;
     284             :   }
     285             : 
     286           0 :   group->cipher = string_to_cipher (cipher);
     287           0 :   if (TALER_DENOMINATION_INVALID == group->cipher)
     288             :   {
     289           0 :     GNUNET_break_op (0);
     290           0 :     return GNUNET_SYSERR;
     291             :   }
     292             : 
     293             :   /* age_mask and suffix must be consistent */
     294           0 :   has_age_restricted_suffix =
     295           0 :     (NULL != strstr (cipher, "+age_restricted"));
     296           0 :   if (has_age_restricted_suffix && age_mask_missing)
     297             :   {
     298           0 :     GNUNET_break_op (0);
     299           0 :     return GNUNET_SYSERR;
     300             :   }
     301             : 
     302           0 :   if (age_mask_missing)
     303           0 :     group->age_mask.bits = 0;
     304             : 
     305           0 :   return GNUNET_OK;
     306             : }
     307             : 
     308             : 
     309             : struct GNUNET_JSON_Specification
     310           0 : TALER_JSON_spec_denomination_group (const char *name,
     311             :                                     const char *currency,
     312             :                                     struct TALER_DenominationGroup *group)
     313             : {
     314           0 :   struct GNUNET_JSON_Specification ret = {
     315             :     .cls = (void *) currency,
     316             :     .parser = &parse_denomination_group,
     317             :     .cleaner = NULL,
     318             :     .field = name,
     319             :     .ptr = group,
     320             :     .ptr_size = sizeof(*group),
     321             :     .size_ptr = NULL,
     322             :   };
     323             : 
     324           0 :   return ret;
     325             : }
     326             : 
     327             : 
     328             : /**
     329             :  * Parse given JSON object to an encrypted contract.
     330             :  *
     331             :  * @param cls closure, NULL
     332             :  * @param root the json object representing data
     333             :  * @param[out] spec where to write the data
     334             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     335             :  */
     336             : static enum GNUNET_GenericReturnValue
     337           0 : parse_econtract (void *cls,
     338             :                  json_t *root,
     339             :                  struct GNUNET_JSON_Specification *spec)
     340             : {
     341           0 :   struct TALER_EncryptedContract *econtract = spec->ptr;
     342             :   struct GNUNET_JSON_Specification ispec[] = {
     343           0 :     GNUNET_JSON_spec_varsize ("econtract",
     344             :                               &econtract->econtract,
     345             :                               &econtract->econtract_size),
     346           0 :     GNUNET_JSON_spec_fixed_auto ("econtract_sig",
     347             :                                  &econtract->econtract_sig),
     348           0 :     GNUNET_JSON_spec_fixed_auto ("contract_pub",
     349             :                                  &econtract->contract_pub),
     350           0 :     GNUNET_JSON_spec_end ()
     351             :   };
     352             :   const char *emsg;
     353             :   unsigned int eline;
     354             : 
     355             :   (void) cls;
     356           0 :   if (GNUNET_OK !=
     357           0 :       GNUNET_JSON_parse (root,
     358             :                          ispec,
     359             :                          &emsg,
     360             :                          &eline))
     361             :   {
     362           0 :     GNUNET_break_op (0);
     363           0 :     return GNUNET_SYSERR;
     364             :   }
     365           0 :   return GNUNET_OK;
     366             : }
     367             : 
     368             : 
     369             : /**
     370             :  * Cleanup data left from parsing encrypted contract.
     371             :  *
     372             :  * @param cls closure, NULL
     373             :  * @param[out] spec where to free the data
     374             :  */
     375             : static void
     376           0 : clean_econtract (void *cls,
     377             :                  struct GNUNET_JSON_Specification *spec)
     378             : {
     379           0 :   struct TALER_EncryptedContract *econtract = spec->ptr;
     380             : 
     381             :   (void) cls;
     382           0 :   GNUNET_free (econtract->econtract);
     383           0 : }
     384             : 
     385             : 
     386             : struct GNUNET_JSON_Specification
     387           0 : TALER_JSON_spec_econtract (const char *name,
     388             :                            struct TALER_EncryptedContract *econtract)
     389             : {
     390           0 :   struct GNUNET_JSON_Specification ret = {
     391             :     .parser = &parse_econtract,
     392             :     .cleaner = &clean_econtract,
     393             :     .cls = NULL,
     394             :     .field = name,
     395             :     .ptr = econtract,
     396             :     .ptr_size = 0,
     397             :     .size_ptr = NULL
     398             :   };
     399             : 
     400           0 :   return ret;
     401             : }
     402             : 
     403             : 
     404             : /**
     405             :  * Parse given JSON object to an age commitmnet
     406             :  *
     407             :  * @param cls closure, NULL
     408             :  * @param root the json object representing data
     409             :  * @param[out] spec where to write the data
     410             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     411             :  */
     412             : static enum GNUNET_GenericReturnValue
     413           0 : parse_age_commitment (void *cls,
     414             :                       json_t *root,
     415             :                       struct GNUNET_JSON_Specification *spec)
     416             : {
     417           0 :   struct TALER_AgeCommitment *age_commitment = spec->ptr;
     418             :   json_t *pk;
     419             :   unsigned int idx;
     420             :   size_t num;
     421             : 
     422             :   (void) cls;
     423           0 :   if ( (NULL == root) ||
     424           0 :        (! json_is_array (root)))
     425             :   {
     426           0 :     GNUNET_break_op (0);
     427           0 :     return GNUNET_SYSERR;
     428             :   }
     429             : 
     430           0 :   num = json_array_size (root);
     431           0 :   if (32 <= num || 0 == num)
     432             :   {
     433           0 :     GNUNET_break_op (0);
     434           0 :     return GNUNET_SYSERR;
     435             :   }
     436             : 
     437           0 :   age_commitment->num = num;
     438           0 :   age_commitment->keys =
     439           0 :     GNUNET_new_array (num,
     440             :                       struct TALER_AgeCommitmentPublicKeyP);
     441             : 
     442           0 :   json_array_foreach (root, idx, pk) {
     443             :     const char *emsg;
     444             :     unsigned int eline;
     445             :     struct GNUNET_JSON_Specification pkspec[] = {
     446           0 :       GNUNET_JSON_spec_fixed_auto (
     447             :         NULL,
     448             :         &age_commitment->keys[idx].pub),
     449           0 :       GNUNET_JSON_spec_end ()
     450             :     };
     451             : 
     452           0 :     if (GNUNET_OK !=
     453           0 :         GNUNET_JSON_parse (pk,
     454             :                            pkspec,
     455             :                            &emsg,
     456             :                            &eline))
     457             :     {
     458           0 :       GNUNET_break_op (0);
     459           0 :       GNUNET_JSON_parse_free (spec);
     460           0 :       return GNUNET_SYSERR;
     461             :     }
     462             :   };
     463             : 
     464           0 :   return GNUNET_OK;
     465             : }
     466             : 
     467             : 
     468             : /**
     469             :  * Cleanup data left fom parsing age commitment
     470             :  *
     471             :  * @param cls closure, NULL
     472             :  * @param[out] spec where to free the data
     473             :  */
     474             : static void
     475           0 : clean_age_commitment (void *cls,
     476             :                       struct GNUNET_JSON_Specification *spec)
     477             : {
     478           0 :   struct TALER_AgeCommitment *age_commitment = spec->ptr;
     479             : 
     480             :   (void) cls;
     481             : 
     482           0 :   if (NULL == age_commitment ||
     483           0 :       NULL == age_commitment->keys)
     484           0 :     return;
     485             : 
     486           0 :   age_commitment->num = 0;
     487           0 :   GNUNET_free (age_commitment->keys);
     488             : }
     489             : 
     490             : 
     491             : struct GNUNET_JSON_Specification
     492           0 : TALER_JSON_spec_age_commitment (const char *name,
     493             :                                 struct TALER_AgeCommitment *age_commitment)
     494             : {
     495           0 :   struct GNUNET_JSON_Specification ret = {
     496             :     .parser = &parse_age_commitment,
     497             :     .cleaner = &clean_age_commitment,
     498             :     .cls = NULL,
     499             :     .field = name,
     500             :     .ptr = age_commitment,
     501             :     .ptr_size = 0,
     502             :     .size_ptr = NULL
     503             :   };
     504             : 
     505           0 :   return ret;
     506             : }
     507             : 
     508             : 
     509             : /**
     510             :  * Parse given JSON object to denomination public key.
     511             :  *
     512             :  * @param cls closure, NULL
     513             :  * @param root the json object representing data
     514             :  * @param[out] spec where to write the data
     515             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     516             :  */
     517             : static enum GNUNET_GenericReturnValue
     518           0 : parse_denom_pub (void *cls,
     519             :                  json_t *root,
     520             :                  struct GNUNET_JSON_Specification *spec)
     521             : {
     522           0 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     523             :   const char *cipher;
     524           0 :   bool age_mask_missing = false;
     525             :   struct GNUNET_JSON_Specification dspec[] = {
     526           0 :     GNUNET_JSON_spec_string ("cipher",
     527             :                              &cipher),
     528           0 :     GNUNET_JSON_spec_mark_optional (
     529             :       GNUNET_JSON_spec_uint32 ("age_mask",
     530             :                                &denom_pub->age_mask.bits),
     531             :       &age_mask_missing),
     532           0 :     GNUNET_JSON_spec_end ()
     533             :   };
     534             :   const char *emsg;
     535             :   unsigned int eline;
     536             : 
     537             :   (void) cls;
     538           0 :   if (GNUNET_OK !=
     539           0 :       GNUNET_JSON_parse (root,
     540             :                          dspec,
     541             :                          &emsg,
     542             :                          &eline))
     543             :   {
     544           0 :     GNUNET_break_op (0);
     545           0 :     return GNUNET_SYSERR;
     546             :   }
     547             : 
     548           0 :   if (age_mask_missing)
     549           0 :     denom_pub->age_mask.bits = 0;
     550             : 
     551           0 :   denom_pub->cipher = string_to_cipher (cipher);
     552           0 :   switch (denom_pub->cipher)
     553             :   {
     554           0 :   case TALER_DENOMINATION_RSA:
     555             :     {
     556             :       struct GNUNET_JSON_Specification ispec[] = {
     557           0 :         GNUNET_JSON_spec_rsa_public_key (
     558             :           "rsa_public_key",
     559             :           &denom_pub->details.rsa_public_key),
     560           0 :         GNUNET_JSON_spec_end ()
     561             :       };
     562             : 
     563           0 :       if (GNUNET_OK !=
     564           0 :           GNUNET_JSON_parse (root,
     565             :                              ispec,
     566             :                              &emsg,
     567             :                              &eline))
     568             :       {
     569           0 :         GNUNET_break_op (0);
     570           0 :         return GNUNET_SYSERR;
     571             :       }
     572           0 :       return GNUNET_OK;
     573             :     }
     574           0 :   case TALER_DENOMINATION_CS:
     575             :     {
     576             :       struct GNUNET_JSON_Specification ispec[] = {
     577           0 :         GNUNET_JSON_spec_fixed ("cs_public_key",
     578           0 :                                 &denom_pub->details.cs_public_key,
     579             :                                 sizeof (denom_pub->details.cs_public_key)),
     580           0 :         GNUNET_JSON_spec_end ()
     581             :       };
     582             : 
     583           0 :       if (GNUNET_OK !=
     584           0 :           GNUNET_JSON_parse (root,
     585             :                              ispec,
     586             :                              &emsg,
     587             :                              &eline))
     588             :       {
     589           0 :         GNUNET_break_op (0);
     590           0 :         return GNUNET_SYSERR;
     591             :       }
     592           0 :       return GNUNET_OK;
     593             :     }
     594           0 :   default:
     595           0 :     GNUNET_break_op (0);
     596           0 :     return GNUNET_SYSERR;
     597             :   }
     598             : }
     599             : 
     600             : 
     601             : /**
     602             :  * Cleanup data left from parsing denomination public key.
     603             :  *
     604             :  * @param cls closure, NULL
     605             :  * @param[out] spec where to free the data
     606             :  */
     607             : static void
     608           0 : clean_denom_pub (void *cls,
     609             :                  struct GNUNET_JSON_Specification *spec)
     610             : {
     611           0 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     612             : 
     613             :   (void) cls;
     614           0 :   TALER_denom_pub_free (denom_pub);
     615           0 : }
     616             : 
     617             : 
     618             : struct GNUNET_JSON_Specification
     619           0 : TALER_JSON_spec_denom_pub (const char *field,
     620             :                            struct TALER_DenominationPublicKey *pk)
     621             : {
     622           0 :   struct GNUNET_JSON_Specification ret = {
     623             :     .parser = &parse_denom_pub,
     624             :     .cleaner = &clean_denom_pub,
     625             :     .field = field,
     626             :     .ptr = pk
     627             :   };
     628             : 
     629           0 :   pk->cipher = TALER_DENOMINATION_INVALID;
     630           0 :   return ret;
     631             : }
     632             : 
     633             : 
     634             : /**
     635             :  * Parse given JSON object partially into a denomination public key.
     636             :  *
     637             :  * Depending on the cipher in cls, it parses the corresponding public key type.
     638             :  *
     639             :  * @param cls closure, enum TALER_DenominationCipher
     640             :  * @param root the json object representing data
     641             :  * @param[out] spec where to write the data
     642             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     643             :  */
     644             : static enum GNUNET_GenericReturnValue
     645           0 : parse_denom_pub_cipher (void *cls,
     646             :                         json_t *root,
     647             :                         struct GNUNET_JSON_Specification *spec)
     648             : {
     649           0 :   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
     650           0 :   enum TALER_DenominationCipher cipher =
     651           0 :     (enum TALER_DenominationCipher) (long) cls;
     652             :   const char *emsg;
     653             :   unsigned int eline;
     654             : 
     655           0 :   switch (cipher)
     656             :   {
     657           0 :   case TALER_DENOMINATION_RSA:
     658             :     {
     659             :       struct GNUNET_JSON_Specification ispec[] = {
     660           0 :         GNUNET_JSON_spec_rsa_public_key (
     661             :           "rsa_pub",
     662             :           &denom_pub->details.rsa_public_key),
     663           0 :         GNUNET_JSON_spec_end ()
     664             :       };
     665             : 
     666           0 :       if (GNUNET_OK !=
     667           0 :           GNUNET_JSON_parse (root,
     668             :                              ispec,
     669             :                              &emsg,
     670             :                              &eline))
     671             :       {
     672           0 :         GNUNET_break_op (0);
     673           0 :         return GNUNET_SYSERR;
     674             :       }
     675           0 :       return GNUNET_OK;
     676             :     }
     677           0 :   case TALER_DENOMINATION_CS:
     678             :     {
     679             :       struct GNUNET_JSON_Specification ispec[] = {
     680           0 :         GNUNET_JSON_spec_fixed ("cs_pub",
     681           0 :                                 &denom_pub->details.cs_public_key,
     682             :                                 sizeof (denom_pub->details.cs_public_key)),
     683           0 :         GNUNET_JSON_spec_end ()
     684             :       };
     685             : 
     686           0 :       if (GNUNET_OK !=
     687           0 :           GNUNET_JSON_parse (root,
     688             :                              ispec,
     689             :                              &emsg,
     690             :                              &eline))
     691             :       {
     692           0 :         GNUNET_break_op (0);
     693           0 :         return GNUNET_SYSERR;
     694             :       }
     695           0 :       return GNUNET_OK;
     696             :     }
     697           0 :   default:
     698           0 :     GNUNET_break_op (0);
     699           0 :     return GNUNET_SYSERR;
     700             :   }
     701             : }
     702             : 
     703             : 
     704             : struct GNUNET_JSON_Specification
     705           0 : TALER_JSON_spec_denom_pub_cipher (const char *field,
     706             :                                   enum TALER_DenominationCipher cipher,
     707             :                                   struct TALER_DenominationPublicKey *pk)
     708             : {
     709           0 :   struct GNUNET_JSON_Specification ret = {
     710             :     .parser = &parse_denom_pub_cipher,
     711             :     .cleaner = &clean_denom_pub,
     712             :     .field = field,
     713           0 :     .cls = (void *) cipher,
     714             :     .ptr = pk
     715             :   };
     716             : 
     717           0 :   return ret;
     718             : }
     719             : 
     720             : 
     721             : /**
     722             :  * Parse given JSON object to denomination signature.
     723             :  *
     724             :  * @param cls closure, NULL
     725             :  * @param root the json object representing data
     726             :  * @param[out] spec where to write the data
     727             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     728             :  */
     729             : static enum GNUNET_GenericReturnValue
     730           0 : parse_denom_sig (void *cls,
     731             :                  json_t *root,
     732             :                  struct GNUNET_JSON_Specification *spec)
     733             : {
     734           0 :   struct TALER_DenominationSignature *denom_sig = spec->ptr;
     735             :   const char *cipher;
     736             :   struct GNUNET_JSON_Specification dspec[] = {
     737           0 :     GNUNET_JSON_spec_string ("cipher",
     738             :                              &cipher),
     739           0 :     GNUNET_JSON_spec_end ()
     740             :   };
     741             :   const char *emsg;
     742             :   unsigned int eline;
     743             : 
     744             :   (void) cls;
     745           0 :   if (GNUNET_OK !=
     746           0 :       GNUNET_JSON_parse (root,
     747             :                          dspec,
     748             :                          &emsg,
     749             :                          &eline))
     750             :   {
     751           0 :     GNUNET_break_op (0);
     752           0 :     return GNUNET_SYSERR;
     753             :   }
     754           0 :   denom_sig->cipher = string_to_cipher (cipher);
     755           0 :   switch (denom_sig->cipher)
     756             :   {
     757           0 :   case TALER_DENOMINATION_RSA:
     758             :     {
     759             :       struct GNUNET_JSON_Specification ispec[] = {
     760           0 :         GNUNET_JSON_spec_rsa_signature (
     761             :           "rsa_signature",
     762             :           &denom_sig->details.rsa_signature),
     763           0 :         GNUNET_JSON_spec_end ()
     764             :       };
     765             : 
     766           0 :       if (GNUNET_OK !=
     767           0 :           GNUNET_JSON_parse (root,
     768             :                              ispec,
     769             :                              &emsg,
     770             :                              &eline))
     771             :       {
     772           0 :         GNUNET_break_op (0);
     773           0 :         return GNUNET_SYSERR;
     774             :       }
     775           0 :       return GNUNET_OK;
     776             :     }
     777           0 :   case TALER_DENOMINATION_CS:
     778             :     {
     779             :       struct GNUNET_JSON_Specification ispec[] = {
     780           0 :         GNUNET_JSON_spec_fixed_auto ("cs_signature_r",
     781             :                                      &denom_sig->details.cs_signature.r_point),
     782           0 :         GNUNET_JSON_spec_fixed_auto ("cs_signature_s",
     783             :                                      &denom_sig->details.cs_signature.s_scalar),
     784           0 :         GNUNET_JSON_spec_end ()
     785             :       };
     786             : 
     787           0 :       if (GNUNET_OK !=
     788           0 :           GNUNET_JSON_parse (root,
     789             :                              ispec,
     790             :                              &emsg,
     791             :                              &eline))
     792             :       {
     793           0 :         GNUNET_break_op (0);
     794           0 :         return GNUNET_SYSERR;
     795             :       }
     796           0 :       return GNUNET_OK;
     797             :     }
     798           0 :   default:
     799           0 :     GNUNET_break_op (0);
     800           0 :     return GNUNET_SYSERR;
     801             :   }
     802             : }
     803             : 
     804             : 
     805             : /**
     806             :  * Cleanup data left from parsing denomination public key.
     807             :  *
     808             :  * @param cls closure, NULL
     809             :  * @param[out] spec where to free the data
     810             :  */
     811             : static void
     812           0 : clean_denom_sig (void *cls,
     813             :                  struct GNUNET_JSON_Specification *spec)
     814             : {
     815           0 :   struct TALER_DenominationSignature *denom_sig = spec->ptr;
     816             : 
     817             :   (void) cls;
     818           0 :   TALER_denom_sig_free (denom_sig);
     819           0 : }
     820             : 
     821             : 
     822             : struct GNUNET_JSON_Specification
     823           0 : TALER_JSON_spec_denom_sig (const char *field,
     824             :                            struct TALER_DenominationSignature *sig)
     825             : {
     826           0 :   struct GNUNET_JSON_Specification ret = {
     827             :     .parser = &parse_denom_sig,
     828             :     .cleaner = &clean_denom_sig,
     829             :     .field = field,
     830             :     .ptr = sig
     831             :   };
     832             : 
     833           0 :   sig->cipher = TALER_DENOMINATION_INVALID;
     834           0 :   return ret;
     835             : }
     836             : 
     837             : 
     838             : /**
     839             :  * Parse given JSON object to blinded denomination signature.
     840             :  *
     841             :  * @param cls closure, NULL
     842             :  * @param root the json object representing data
     843             :  * @param[out] spec where to write the data
     844             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     845             :  */
     846             : static enum GNUNET_GenericReturnValue
     847           0 : parse_blinded_denom_sig (void *cls,
     848             :                          json_t *root,
     849             :                          struct GNUNET_JSON_Specification *spec)
     850             : {
     851           0 :   struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
     852             :   const char *cipher;
     853             :   struct GNUNET_JSON_Specification dspec[] = {
     854           0 :     GNUNET_JSON_spec_string ("cipher",
     855             :                              &cipher),
     856           0 :     GNUNET_JSON_spec_end ()
     857             :   };
     858             :   const char *emsg;
     859             :   unsigned int eline;
     860             : 
     861             :   (void) cls;
     862           0 :   if (GNUNET_OK !=
     863           0 :       GNUNET_JSON_parse (root,
     864             :                          dspec,
     865             :                          &emsg,
     866             :                          &eline))
     867             :   {
     868           0 :     GNUNET_break_op (0);
     869           0 :     return GNUNET_SYSERR;
     870             :   }
     871           0 :   denom_sig->cipher = string_to_cipher (cipher);
     872           0 :   switch (denom_sig->cipher)
     873             :   {
     874           0 :   case TALER_DENOMINATION_RSA:
     875             :     {
     876             :       struct GNUNET_JSON_Specification ispec[] = {
     877           0 :         GNUNET_JSON_spec_rsa_signature (
     878             :           "blinded_rsa_signature",
     879             :           &denom_sig->details.blinded_rsa_signature),
     880           0 :         GNUNET_JSON_spec_end ()
     881             :       };
     882             : 
     883           0 :       if (GNUNET_OK !=
     884           0 :           GNUNET_JSON_parse (root,
     885             :                              ispec,
     886             :                              &emsg,
     887             :                              &eline))
     888             :       {
     889           0 :         GNUNET_break_op (0);
     890           0 :         return GNUNET_SYSERR;
     891             :       }
     892           0 :       return GNUNET_OK;
     893             :     }
     894           0 :   case TALER_DENOMINATION_CS:
     895             :     {
     896             :       struct GNUNET_JSON_Specification ispec[] = {
     897           0 :         GNUNET_JSON_spec_uint32 ("b",
     898           0 :                                  &denom_sig->details.blinded_cs_answer.b),
     899           0 :         GNUNET_JSON_spec_fixed_auto ("s",
     900             :                                      &denom_sig->details.blinded_cs_answer.
     901             :                                      s_scalar),
     902           0 :         GNUNET_JSON_spec_end ()
     903             :       };
     904             : 
     905           0 :       if (GNUNET_OK !=
     906           0 :           GNUNET_JSON_parse (root,
     907             :                              ispec,
     908             :                              &emsg,
     909             :                              &eline))
     910             :       {
     911           0 :         GNUNET_break_op (0);
     912           0 :         return GNUNET_SYSERR;
     913             :       }
     914           0 :       return GNUNET_OK;
     915             :     }
     916             :     break;
     917           0 :   default:
     918           0 :     GNUNET_break_op (0);
     919           0 :     return GNUNET_SYSERR;
     920             :   }
     921             : }
     922             : 
     923             : 
     924             : /**
     925             :  * Cleanup data left from parsing denomination public key.
     926             :  *
     927             :  * @param cls closure, NULL
     928             :  * @param[out] spec where to free the data
     929             :  */
     930             : static void
     931           0 : clean_blinded_denom_sig (void *cls,
     932             :                          struct GNUNET_JSON_Specification *spec)
     933             : {
     934           0 :   struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
     935             : 
     936             :   (void) cls;
     937           0 :   TALER_blinded_denom_sig_free (denom_sig);
     938           0 : }
     939             : 
     940             : 
     941             : struct GNUNET_JSON_Specification
     942           0 : TALER_JSON_spec_blinded_denom_sig (
     943             :   const char *field,
     944             :   struct TALER_BlindedDenominationSignature *sig)
     945             : {
     946           0 :   struct GNUNET_JSON_Specification ret = {
     947             :     .parser = &parse_blinded_denom_sig,
     948             :     .cleaner = &clean_blinded_denom_sig,
     949             :     .field = field,
     950             :     .ptr = sig
     951             :   };
     952             : 
     953           0 :   sig->cipher = TALER_DENOMINATION_INVALID;
     954           0 :   return ret;
     955             : }
     956             : 
     957             : 
     958             : /**
     959             :  * Parse given JSON object to blinded planchet.
     960             :  *
     961             :  * @param cls closure, NULL
     962             :  * @param root the json object representing data
     963             :  * @param[out] spec where to write the data
     964             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
     965             :  */
     966             : static enum GNUNET_GenericReturnValue
     967           0 : parse_blinded_planchet (void *cls,
     968             :                         json_t *root,
     969             :                         struct GNUNET_JSON_Specification *spec)
     970             : {
     971           0 :   struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
     972             :   const char *cipher;
     973             :   struct GNUNET_JSON_Specification dspec[] = {
     974           0 :     GNUNET_JSON_spec_string ("cipher",
     975             :                              &cipher),
     976           0 :     GNUNET_JSON_spec_end ()
     977             :   };
     978             :   const char *emsg;
     979             :   unsigned int eline;
     980             : 
     981             :   (void) cls;
     982           0 :   if (GNUNET_OK !=
     983           0 :       GNUNET_JSON_parse (root,
     984             :                          dspec,
     985             :                          &emsg,
     986             :                          &eline))
     987             :   {
     988           0 :     GNUNET_break_op (0);
     989           0 :     return GNUNET_SYSERR;
     990             :   }
     991           0 :   blinded_planchet->cipher = string_to_cipher (cipher);
     992           0 :   switch (blinded_planchet->cipher)
     993             :   {
     994           0 :   case TALER_DENOMINATION_RSA:
     995             :     {
     996             :       struct GNUNET_JSON_Specification ispec[] = {
     997           0 :         GNUNET_JSON_spec_varsize (
     998             :           "rsa_blinded_planchet",
     999             :           &blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
    1000             :           &blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size),
    1001           0 :         GNUNET_JSON_spec_end ()
    1002             :       };
    1003             : 
    1004           0 :       if (GNUNET_OK !=
    1005           0 :           GNUNET_JSON_parse (root,
    1006             :                              ispec,
    1007             :                              &emsg,
    1008             :                              &eline))
    1009             :       {
    1010           0 :         GNUNET_break_op (0);
    1011           0 :         return GNUNET_SYSERR;
    1012             :       }
    1013           0 :       return GNUNET_OK;
    1014             :     }
    1015           0 :   case TALER_DENOMINATION_CS:
    1016             :     {
    1017             :       struct GNUNET_JSON_Specification ispec[] = {
    1018           0 :         GNUNET_JSON_spec_fixed_auto (
    1019             :           "cs_nonce",
    1020             :           &blinded_planchet->details.cs_blinded_planchet.nonce),
    1021           0 :         GNUNET_JSON_spec_fixed_auto (
    1022             :           "cs_blinded_c0",
    1023             :           &blinded_planchet->details.cs_blinded_planchet.c[0]),
    1024           0 :         GNUNET_JSON_spec_fixed_auto (
    1025             :           "cs_blinded_c1",
    1026             :           &blinded_planchet->details.cs_blinded_planchet.c[1]),
    1027           0 :         GNUNET_JSON_spec_end ()
    1028             :       };
    1029             : 
    1030           0 :       if (GNUNET_OK !=
    1031           0 :           GNUNET_JSON_parse (root,
    1032             :                              ispec,
    1033             :                              &emsg,
    1034             :                              &eline))
    1035             :       {
    1036           0 :         GNUNET_break_op (0);
    1037           0 :         return GNUNET_SYSERR;
    1038             :       }
    1039           0 :       return GNUNET_OK;
    1040             :     }
    1041             :     break;
    1042           0 :   default:
    1043           0 :     GNUNET_break_op (0);
    1044           0 :     return GNUNET_SYSERR;
    1045             :   }
    1046             : }
    1047             : 
    1048             : 
    1049             : /**
    1050             :  * Cleanup data left from parsing blinded planchet.
    1051             :  *
    1052             :  * @param cls closure, NULL
    1053             :  * @param[out] spec where to free the data
    1054             :  */
    1055             : static void
    1056           0 : clean_blinded_planchet (void *cls,
    1057             :                         struct GNUNET_JSON_Specification *spec)
    1058             : {
    1059           0 :   struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
    1060             : 
    1061             :   (void) cls;
    1062           0 :   TALER_blinded_planchet_free (blinded_planchet);
    1063           0 : }
    1064             : 
    1065             : 
    1066             : struct GNUNET_JSON_Specification
    1067           0 : TALER_JSON_spec_blinded_planchet (const char *field,
    1068             :                                   struct TALER_BlindedPlanchet *blinded_planchet)
    1069             : {
    1070           0 :   struct GNUNET_JSON_Specification ret = {
    1071             :     .parser = &parse_blinded_planchet,
    1072             :     .cleaner = &clean_blinded_planchet,
    1073             :     .field = field,
    1074             :     .ptr = blinded_planchet
    1075             :   };
    1076             : 
    1077           0 :   blinded_planchet->cipher = TALER_DENOMINATION_INVALID;
    1078           0 :   return ret;
    1079             : }
    1080             : 
    1081             : 
    1082             : /**
    1083             :  * Parse given JSON object to exchange withdraw values (/csr).
    1084             :  *
    1085             :  * @param cls closure, NULL
    1086             :  * @param root the json object representing data
    1087             :  * @param[out] spec where to write the data
    1088             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1089             :  */
    1090             : static enum GNUNET_GenericReturnValue
    1091           0 : parse_exchange_withdraw_values (void *cls,
    1092             :                                 json_t *root,
    1093             :                                 struct GNUNET_JSON_Specification *spec)
    1094             : {
    1095           0 :   struct TALER_ExchangeWithdrawValues *ewv = spec->ptr;
    1096             :   const char *cipher;
    1097             :   struct GNUNET_JSON_Specification dspec[] = {
    1098           0 :     GNUNET_JSON_spec_string ("cipher",
    1099             :                              &cipher),
    1100           0 :     GNUNET_JSON_spec_end ()
    1101             :   };
    1102             :   const char *emsg;
    1103             :   unsigned int eline;
    1104             : 
    1105             :   (void) cls;
    1106           0 :   if (GNUNET_OK !=
    1107           0 :       GNUNET_JSON_parse (root,
    1108             :                          dspec,
    1109             :                          &emsg,
    1110             :                          &eline))
    1111             :   {
    1112           0 :     GNUNET_break_op (0);
    1113           0 :     return GNUNET_SYSERR;
    1114             :   }
    1115           0 :   ewv->cipher = string_to_cipher (cipher);
    1116           0 :   switch (ewv->cipher)
    1117             :   {
    1118           0 :   case TALER_DENOMINATION_RSA:
    1119           0 :     return GNUNET_OK;
    1120           0 :   case TALER_DENOMINATION_CS:
    1121             :     {
    1122             :       struct GNUNET_JSON_Specification ispec[] = {
    1123           0 :         GNUNET_JSON_spec_fixed (
    1124             :           "r_pub_0",
    1125           0 :           &ewv->details.cs_values.r_pub[0],
    1126             :           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
    1127           0 :         GNUNET_JSON_spec_fixed (
    1128             :           "r_pub_1",
    1129           0 :           &ewv->details.cs_values.r_pub[1],
    1130             :           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
    1131           0 :         GNUNET_JSON_spec_end ()
    1132             :       };
    1133             : 
    1134           0 :       if (GNUNET_OK !=
    1135           0 :           GNUNET_JSON_parse (root,
    1136             :                              ispec,
    1137             :                              &emsg,
    1138             :                              &eline))
    1139             :       {
    1140           0 :         GNUNET_break_op (0);
    1141           0 :         return GNUNET_SYSERR;
    1142             :       }
    1143           0 :       return GNUNET_OK;
    1144             :     }
    1145           0 :   default:
    1146           0 :     GNUNET_break_op (0);
    1147           0 :     return GNUNET_SYSERR;
    1148             :   }
    1149             : }
    1150             : 
    1151             : 
    1152             : struct GNUNET_JSON_Specification
    1153           0 : TALER_JSON_spec_exchange_withdraw_values (
    1154             :   const char *field,
    1155             :   struct TALER_ExchangeWithdrawValues *ewv)
    1156             : {
    1157           0 :   struct GNUNET_JSON_Specification ret = {
    1158             :     .parser = &parse_exchange_withdraw_values,
    1159             :     .field = field,
    1160             :     .ptr = ewv
    1161             :   };
    1162             : 
    1163           0 :   ewv->cipher = TALER_DENOMINATION_INVALID;
    1164           0 :   return ret;
    1165             : }
    1166             : 
    1167             : 
    1168             : /**
    1169             :  * Closure for #parse_i18n_string.
    1170             :  */
    1171             : struct I18nContext
    1172             : {
    1173             :   /**
    1174             :    * Language pattern to match.
    1175             :    */
    1176             :   char *lp;
    1177             : 
    1178             :   /**
    1179             :    * Name of the field to match.
    1180             :    */
    1181             :   const char *field;
    1182             : };
    1183             : 
    1184             : 
    1185             : /**
    1186             :  * Parse given JSON object to internationalized string.
    1187             :  *
    1188             :  * @param cls closure, our `struct I18nContext *`
    1189             :  * @param root the json object representing data
    1190             :  * @param[out] spec where to write the data
    1191             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    1192             :  */
    1193             : static enum GNUNET_GenericReturnValue
    1194           0 : parse_i18n_string (void *cls,
    1195             :                    json_t *root,
    1196             :                    struct GNUNET_JSON_Specification *spec)
    1197             : {
    1198           0 :   struct I18nContext *ctx = cls;
    1199             :   json_t *i18n;
    1200             :   json_t *val;
    1201             : 
    1202             :   {
    1203             :     char *i18nf;
    1204             : 
    1205           0 :     GNUNET_asprintf (&i18nf,
    1206             :                      "%s_i18n",
    1207             :                      ctx->field);
    1208           0 :     i18n = json_object_get (root,
    1209             :                             i18nf);
    1210           0 :     GNUNET_free (i18nf);
    1211             :   }
    1212             : 
    1213           0 :   val = json_object_get (root,
    1214             :                          ctx->field);
    1215           0 :   if ( (NULL != i18n) &&
    1216           0 :        (NULL != ctx->lp) )
    1217             :   {
    1218           0 :     double best = 0.0;
    1219             :     json_t *pos;
    1220             :     const char *lang;
    1221             : 
    1222           0 :     json_object_foreach (i18n, lang, pos)
    1223             :     {
    1224             :       double score;
    1225             : 
    1226           0 :       score = TALER_language_matches (ctx->lp,
    1227             :                                       lang);
    1228           0 :       if (score > best)
    1229             :       {
    1230           0 :         best = score;
    1231           0 :         val = pos;
    1232             :       }
    1233             :     }
    1234             :   }
    1235             : 
    1236             :   {
    1237             :     const char *str;
    1238             : 
    1239           0 :     str = json_string_value (val);
    1240           0 :     if (NULL == str)
    1241             :     {
    1242           0 :       GNUNET_break_op (0);
    1243           0 :       return GNUNET_SYSERR;
    1244             :     }
    1245           0 :     *(const char **) spec->ptr = str;
    1246             :   }
    1247           0 :   return GNUNET_OK;
    1248             : }
    1249             : 
    1250             : 
    1251             : /**
    1252             :  * Function called to clean up data from earlier parsing.
    1253             :  *
    1254             :  * @param cls closure
    1255             :  * @param spec our specification entry with data to clean.
    1256             :  */
    1257             : static void
    1258           0 : i18n_cleaner (void *cls,
    1259             :               struct GNUNET_JSON_Specification *spec)
    1260             : {
    1261           0 :   struct I18nContext *ctx = cls;
    1262             : 
    1263             :   (void) spec;
    1264           0 :   GNUNET_free (ctx->lp);
    1265           0 :   GNUNET_free (ctx);
    1266           0 : }
    1267             : 
    1268             : 
    1269             : struct GNUNET_JSON_Specification
    1270           0 : TALER_JSON_spec_i18n_string (const char *name,
    1271             :                              const char *language_pattern,
    1272             :                              const char **strptr)
    1273             : {
    1274           0 :   struct I18nContext *ctx = GNUNET_new (struct I18nContext);
    1275           0 :   struct GNUNET_JSON_Specification ret = {
    1276             :     .parser = &parse_i18n_string,
    1277             :     .cleaner = &i18n_cleaner,
    1278             :     .cls = ctx,
    1279             :     .field = NULL, /* we want the main object */
    1280             :     .ptr = strptr,
    1281             :     .ptr_size = 0,
    1282             :     .size_ptr = NULL
    1283             :   };
    1284             : 
    1285           0 :   ctx->lp = (NULL != language_pattern) ? GNUNET_strdup (language_pattern) :
    1286             :             NULL;
    1287           0 :   ctx->field = name;
    1288           0 :   *strptr = NULL;
    1289           0 :   return ret;
    1290             : }
    1291             : 
    1292             : 
    1293             : struct GNUNET_JSON_Specification
    1294           0 : TALER_JSON_spec_i18n_str (const char *name,
    1295             :                           const char **strptr)
    1296             : {
    1297           0 :   const char *lang = getenv ("LANG");
    1298             :   char *dot;
    1299             :   char *l;
    1300             :   struct GNUNET_JSON_Specification ret;
    1301             : 
    1302           0 :   if (NULL != lang)
    1303             :   {
    1304           0 :     dot = strchr (lang,
    1305             :                   '.');
    1306           0 :     if (NULL == dot)
    1307           0 :       l = GNUNET_strdup (lang);
    1308             :     else
    1309           0 :       l = GNUNET_strndup (lang,
    1310             :                           dot - lang);
    1311             :   }
    1312             :   else
    1313             :   {
    1314           0 :     l = NULL;
    1315             :   }
    1316           0 :   ret = TALER_JSON_spec_i18n_string (name,
    1317             :                                      l,
    1318             :                                      strptr);
    1319           0 :   GNUNET_free (l);
    1320           0 :   return ret;
    1321             : }
    1322             : 
    1323             : 
    1324             : /* end of json/json_helper.c */

Generated by: LCOV version 1.14