LCOV - code coverage report
Current view: top level - pq - pq_result_helper.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 289 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2022 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 pq/pq_result_helper.c
      18             :  * @brief functions to initialize parameter arrays
      19             :  * @author Christian Grothoff
      20             :  */
      21             : #include "platform.h"
      22             : #include <gnunet/gnunet_util_lib.h>
      23             : #include "taler_pq_lib.h"
      24             : 
      25             : 
      26             : /**
      27             :  * Extract a currency amount from a query result according to the
      28             :  * given specification.
      29             :  *
      30             :  * @param result the result to extract the amount from
      31             :  * @param row which row of the result to extract the amount from (needed as results can have multiple rows)
      32             :  * @param currency currency to use for @a r_amount_nbo
      33             :  * @param val_name name of the column with the amount's "value", must include the substring "_val".
      34             :  * @param frac_name name of the column with the amount's "fractional" value, must include the substring "_frac".
      35             :  * @param[out] r_amount_nbo where to store the amount, in network byte order
      36             :  * @return
      37             :  *   #GNUNET_YES if all results could be extracted
      38             :  *   #GNUNET_NO if at least one result was NULL
      39             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
      40             :  */
      41             : static enum GNUNET_GenericReturnValue
      42           0 : extract_amount_nbo_helper (PGresult *result,
      43             :                            int row,
      44             :                            const char *currency,
      45             :                            const char *val_name,
      46             :                            const char *frac_name,
      47             :                            struct TALER_AmountNBO *r_amount_nbo)
      48             : {
      49             :   int val_num;
      50             :   int frac_num;
      51             :   int len;
      52             : 
      53             :   /* These checks are simply to check that clients obey by our naming
      54             :      conventions, and not for any functional reason */
      55           0 :   GNUNET_assert (NULL !=
      56             :                  strstr (val_name,
      57             :                          "_val"));
      58           0 :   GNUNET_assert (NULL !=
      59             :                  strstr (frac_name,
      60             :                          "_frac"));
      61             :   /* Set return value to invalid in case we don't finish */
      62           0 :   memset (r_amount_nbo,
      63             :           0,
      64             :           sizeof (struct TALER_AmountNBO));
      65           0 :   val_num = PQfnumber (result,
      66             :                        val_name);
      67           0 :   frac_num = PQfnumber (result,
      68             :                         frac_name);
      69           0 :   if (val_num < 0)
      70             :   {
      71           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      72             :                 "Field `%s' does not exist in result\n",
      73             :                 val_name);
      74           0 :     return GNUNET_SYSERR;
      75             :   }
      76           0 :   if (frac_num < 0)
      77             :   {
      78           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      79             :                 "Field `%s' does not exist in result\n",
      80             :                 frac_name);
      81           0 :     return GNUNET_SYSERR;
      82             :   }
      83           0 :   if ( (PQgetisnull (result,
      84             :                      row,
      85           0 :                      val_num)) ||
      86           0 :        (PQgetisnull (result,
      87             :                      row,
      88             :                      frac_num)) )
      89             :   {
      90           0 :     return GNUNET_NO;
      91             :   }
      92             :   /* Note that Postgres stores value in NBO internally,
      93             :      so no conversion needed in this case */
      94           0 :   r_amount_nbo->value = *(uint64_t *) PQgetvalue (result,
      95             :                                                   row,
      96             :                                                   val_num);
      97           0 :   r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result,
      98             :                                                      row,
      99             :                                                      frac_num);
     100           0 :   if (GNUNET_ntohll (r_amount_nbo->value) >= TALER_AMOUNT_MAX_VALUE)
     101             :   {
     102           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     103             :                 "Field `%s' exceeds legal range\n",
     104             :                 val_name);
     105           0 :     return GNUNET_SYSERR;
     106             :   }
     107           0 :   if (ntohl (r_amount_nbo->fraction) >= TALER_AMOUNT_FRAC_BASE)
     108             :   {
     109           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     110             :                 "Field `%s' exceeds legal range\n",
     111             :                 frac_name);
     112           0 :     return GNUNET_SYSERR;
     113             :   }
     114           0 :   len = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
     115             :                     strlen (currency));
     116           0 :   memcpy (r_amount_nbo->currency,
     117             :           currency,
     118             :           len);
     119           0 :   return GNUNET_OK;
     120             : }
     121             : 
     122             : 
     123             : /**
     124             :  * Extract data from a Postgres database @a result at row @a row.
     125             :  *
     126             :  * @param cls closure, a `const char *` giving the currency
     127             :  * @param result where to extract data from
     128             :  * @param row row to extract data from
     129             :  * @param fname name (or prefix) of the fields to extract from
     130             :  * @param[in,out] dst_size where to store size of result, may be NULL
     131             :  * @param[out] dst where to store the result
     132             :  * @return
     133             :  *   #GNUNET_YES if all results could be extracted
     134             :  *   #GNUNET_NO if at least one result was NULL
     135             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
     136             :  */
     137             : static enum GNUNET_GenericReturnValue
     138           0 : extract_amount_nbo (void *cls,
     139             :                     PGresult *result,
     140             :                     int row,
     141             :                     const char *fname,
     142             :                     size_t *dst_size,
     143             :                     void *dst)
     144             : {
     145           0 :   const char *currency = cls;
     146             :   char *val_name;
     147             :   char *frac_name;
     148             :   enum GNUNET_GenericReturnValue ret;
     149             : 
     150           0 :   if (sizeof (struct TALER_AmountNBO) != *dst_size)
     151             :   {
     152           0 :     GNUNET_break (0);
     153           0 :     return GNUNET_SYSERR;
     154             :   }
     155           0 :   GNUNET_asprintf (&val_name,
     156             :                    "%s_val",
     157             :                    fname);
     158           0 :   GNUNET_asprintf (&frac_name,
     159             :                    "%s_frac",
     160             :                    fname);
     161           0 :   ret = extract_amount_nbo_helper (result,
     162             :                                    row,
     163             :                                    currency,
     164             :                                    val_name,
     165             :                                    frac_name,
     166             :                                    dst);
     167           0 :   GNUNET_free (val_name);
     168           0 :   GNUNET_free (frac_name);
     169           0 :   return ret;
     170             : }
     171             : 
     172             : 
     173             : struct GNUNET_PQ_ResultSpec
     174           0 : TALER_PQ_result_spec_amount_nbo (const char *name,
     175             :                                  const char *currency,
     176             :                                  struct TALER_AmountNBO *amount)
     177             : {
     178           0 :   struct GNUNET_PQ_ResultSpec res = {
     179             :     .conv = &extract_amount_nbo,
     180             :     .cls = (void *) currency,
     181             :     .dst = (void *) amount,
     182             :     .dst_size = sizeof (*amount),
     183             :     .fname = name
     184             :   };
     185             : 
     186           0 :   return res;
     187             : }
     188             : 
     189             : 
     190             : /**
     191             :  * Extract data from a Postgres database @a result at row @a row.
     192             :  *
     193             :  * @param cls closure, a `const char *` giving the currency
     194             :  * @param result where to extract data from
     195             :  * @param row row to extract data from
     196             :  * @param fname name (or prefix) of the fields to extract from
     197             :  * @param[in,out] dst_size where to store size of result, may be NULL
     198             :  * @param[out] dst where to store the result
     199             :  * @return
     200             :  *   #GNUNET_YES if all results could be extracted
     201             :  *   #GNUNET_NO if at least one result was NULL
     202             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
     203             :  */
     204             : static enum GNUNET_GenericReturnValue
     205           0 : extract_amount (void *cls,
     206             :                 PGresult *result,
     207             :                 int row,
     208             :                 const char *fname,
     209             :                 size_t *dst_size,
     210             :                 void *dst)
     211             : {
     212           0 :   const char *currency = cls;
     213           0 :   struct TALER_Amount *r_amount = dst;
     214             :   char *val_name;
     215             :   char *frac_name;
     216             :   struct TALER_AmountNBO amount_nbo;
     217             :   enum GNUNET_GenericReturnValue ret;
     218             : 
     219           0 :   if (sizeof (struct TALER_AmountNBO) != *dst_size)
     220             :   {
     221           0 :     GNUNET_break (0);
     222           0 :     return GNUNET_SYSERR;
     223             :   }
     224           0 :   GNUNET_asprintf (&val_name,
     225             :                    "%s_val",
     226             :                    fname);
     227           0 :   GNUNET_asprintf (&frac_name,
     228             :                    "%s_frac",
     229             :                    fname);
     230           0 :   ret = extract_amount_nbo_helper (result,
     231             :                                    row,
     232             :                                    currency,
     233             :                                    val_name,
     234             :                                    frac_name,
     235             :                                    &amount_nbo);
     236           0 :   if (GNUNET_OK == ret)
     237           0 :     TALER_amount_ntoh (r_amount,
     238             :                        &amount_nbo);
     239             :   else
     240           0 :     memset (r_amount,
     241             :             0,
     242             :             sizeof (struct TALER_Amount));
     243           0 :   GNUNET_free (val_name);
     244           0 :   GNUNET_free (frac_name);
     245           0 :   return ret;
     246             : }
     247             : 
     248             : 
     249             : struct GNUNET_PQ_ResultSpec
     250           0 : TALER_PQ_result_spec_amount (const char *name,
     251             :                              const char *currency,
     252             :                              struct TALER_Amount *amount)
     253             : {
     254           0 :   struct GNUNET_PQ_ResultSpec res = {
     255             :     .conv = &extract_amount,
     256             :     .cls = (void *) currency,
     257             :     .dst = (void *) amount,
     258             :     .dst_size = sizeof (*amount),
     259             :     .fname = name
     260             :   };
     261             : 
     262           0 :   return res;
     263             : }
     264             : 
     265             : 
     266             : /**
     267             :  * Extract data from a Postgres database @a result at row @a row.
     268             :  *
     269             :  * @param cls closure
     270             :  * @param result where to extract data from
     271             :  * @param row row to extract data from
     272             :  * @param fname name (or prefix) of the fields to extract from
     273             :  * @param[in,out] dst_size where to store size of result, may be NULL
     274             :  * @param[out] dst where to store the result
     275             :  * @return
     276             :  *   #GNUNET_YES if all results could be extracted
     277             :  *   #GNUNET_NO if at least one result was NULL
     278             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
     279             :  */
     280             : static enum GNUNET_GenericReturnValue
     281           0 : extract_json (void *cls,
     282             :               PGresult *result,
     283             :               int row,
     284             :               const char *fname,
     285             :               size_t *dst_size,
     286             :               void *dst)
     287             : {
     288           0 :   json_t **j_dst = dst;
     289             :   const char *res;
     290             :   int fnum;
     291             :   json_error_t json_error;
     292             :   size_t slen;
     293             : 
     294             :   (void) cls;
     295             :   (void) dst_size;
     296           0 :   fnum = PQfnumber (result,
     297             :                     fname);
     298           0 :   if (fnum < 0)
     299             :   {
     300           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     301             :                 "Field `%s' does not exist in result\n",
     302             :                 fname);
     303           0 :     return GNUNET_SYSERR;
     304             :   }
     305           0 :   if (PQgetisnull (result,
     306             :                    row,
     307             :                    fnum))
     308           0 :     return GNUNET_NO;
     309           0 :   slen = PQgetlength (result,
     310             :                       row,
     311             :                       fnum);
     312           0 :   res = (const char *) PQgetvalue (result,
     313             :                                    row,
     314             :                                    fnum);
     315           0 :   *j_dst = json_loadb (res,
     316             :                        slen,
     317             :                        JSON_REJECT_DUPLICATES,
     318             :                        &json_error);
     319           0 :   if (NULL == *j_dst)
     320             :   {
     321           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     322             :                 "Failed to parse JSON result for field `%s': %s (%s)\n",
     323             :                 fname,
     324             :                 json_error.text,
     325             :                 json_error.source);
     326           0 :     return GNUNET_SYSERR;
     327             :   }
     328           0 :   return GNUNET_OK;
     329             : }
     330             : 
     331             : 
     332             : /**
     333             :  * Function called to clean up memory allocated
     334             :  * by a #GNUNET_PQ_ResultConverter.
     335             :  *
     336             :  * @param cls closure
     337             :  * @param rd result data to clean up
     338             :  */
     339             : static void
     340           0 : clean_json (void *cls,
     341             :             void *rd)
     342             : {
     343           0 :   json_t **dst = rd;
     344             : 
     345             :   (void) cls;
     346           0 :   if (NULL != *dst)
     347             :   {
     348           0 :     json_decref (*dst);
     349           0 :     *dst = NULL;
     350             :   }
     351           0 : }
     352             : 
     353             : 
     354             : struct GNUNET_PQ_ResultSpec
     355           0 : TALER_PQ_result_spec_json (const char *name,
     356             :                            json_t **jp)
     357             : {
     358           0 :   struct GNUNET_PQ_ResultSpec res = {
     359             :     .conv = &extract_json,
     360             :     .cleaner = &clean_json,
     361             :     .dst = (void *) jp,
     362             :     .fname  = name
     363             :   };
     364             : 
     365           0 :   return res;
     366             : }
     367             : 
     368             : 
     369             : /**
     370             :  * Extract data from a Postgres database @a result at row @a row.
     371             :  *
     372             :  * @param cls closure
     373             :  * @param result where to extract data from
     374             :  * @param row the row to extract data from
     375             :  * @param fname name (or prefix) of the fields to extract from
     376             :  * @param[in,out] dst_size where to store size of result, may be NULL
     377             :  * @param[out] dst where to store the result
     378             :  * @return
     379             :  *   #GNUNET_YES if all results could be extracted
     380             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
     381             :  */
     382             : static enum GNUNET_GenericReturnValue
     383           0 : extract_denom_pub (void *cls,
     384             :                    PGresult *result,
     385             :                    int row,
     386             :                    const char *fname,
     387             :                    size_t *dst_size,
     388             :                    void *dst)
     389             : {
     390           0 :   struct TALER_DenominationPublicKey *pk = dst;
     391             :   size_t len;
     392             :   const char *res;
     393             :   int fnum;
     394             :   uint32_t be[2];
     395             : 
     396             :   (void) cls;
     397             :   (void) dst_size;
     398           0 :   fnum = PQfnumber (result,
     399             :                     fname);
     400           0 :   if (fnum < 0)
     401             :   {
     402           0 :     GNUNET_break (0);
     403           0 :     return GNUNET_SYSERR;
     404             :   }
     405           0 :   if (PQgetisnull (result,
     406             :                    row,
     407             :                    fnum))
     408           0 :     return GNUNET_NO;
     409             : 
     410             :   /* if a field is null, continue but
     411             :    * remember that we now return a different result */
     412           0 :   len = PQgetlength (result,
     413             :                      row,
     414             :                      fnum);
     415           0 :   res = PQgetvalue (result,
     416             :                     row,
     417             :                     fnum);
     418           0 :   if (len < sizeof (be))
     419             :   {
     420           0 :     GNUNET_break (0);
     421           0 :     return GNUNET_SYSERR;
     422             :   }
     423           0 :   memcpy (be,
     424             :           res,
     425             :           sizeof (be));
     426           0 :   res += sizeof (be);
     427           0 :   len -= sizeof (be);
     428           0 :   pk->cipher = ntohl (be[0]);
     429           0 :   pk->age_mask.bits = ntohl (be[1]);
     430           0 :   switch (pk->cipher)
     431             :   {
     432           0 :   case TALER_DENOMINATION_RSA:
     433             :     pk->details.rsa_public_key
     434           0 :       = GNUNET_CRYPTO_rsa_public_key_decode (res,
     435             :                                              len);
     436           0 :     if (NULL == pk->details.rsa_public_key)
     437             :     {
     438           0 :       GNUNET_break (0);
     439           0 :       return GNUNET_SYSERR;
     440             :     }
     441           0 :     return GNUNET_OK;
     442           0 :   case TALER_DENOMINATION_CS:
     443           0 :     if (sizeof (pk->details.cs_public_key) != len)
     444             :     {
     445           0 :       GNUNET_break (0);
     446           0 :       return GNUNET_SYSERR;
     447             :     }
     448           0 :     memcpy (&pk->details.cs_public_key,
     449             :             res,
     450             :             len);
     451           0 :     return GNUNET_OK;
     452           0 :   default:
     453           0 :     GNUNET_break (0);
     454             :   }
     455           0 :   return GNUNET_SYSERR;
     456             : }
     457             : 
     458             : 
     459             : /**
     460             :  * Function called to clean up memory allocated
     461             :  * by a #GNUNET_PQ_ResultConverter.
     462             :  *
     463             :  * @param cls closure
     464             :  * @param rd result data to clean up
     465             :  */
     466             : static void
     467           0 : clean_denom_pub (void *cls,
     468             :                  void *rd)
     469             : {
     470           0 :   struct TALER_DenominationPublicKey *denom_pub = rd;
     471             : 
     472             :   (void) cls;
     473           0 :   TALER_denom_pub_free (denom_pub);
     474           0 : }
     475             : 
     476             : 
     477             : struct GNUNET_PQ_ResultSpec
     478           0 : TALER_PQ_result_spec_denom_pub (const char *name,
     479             :                                 struct TALER_DenominationPublicKey *denom_pub)
     480             : {
     481           0 :   struct GNUNET_PQ_ResultSpec res = {
     482             :     .conv = &extract_denom_pub,
     483             :     .cleaner = &clean_denom_pub,
     484             :     .dst = (void *) denom_pub,
     485             :     .fname = name
     486             :   };
     487             : 
     488           0 :   return res;
     489             : }
     490             : 
     491             : 
     492             : /**
     493             :  * Extract data from a Postgres database @a result at row @a row.
     494             :  *
     495             :  * @param cls closure
     496             :  * @param result where to extract data from
     497             :  * @param row the row to extract data from
     498             :  * @param fname name (or prefix) of the fields to extract from
     499             :  * @param[in,out] dst_size where to store size of result, may be NULL
     500             :  * @param[out] dst where to store the result
     501             :  * @return
     502             :  *   #GNUNET_YES if all results could be extracted
     503             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
     504             :  */
     505             : static enum GNUNET_GenericReturnValue
     506           0 : extract_denom_sig (void *cls,
     507             :                    PGresult *result,
     508             :                    int row,
     509             :                    const char *fname,
     510             :                    size_t *dst_size,
     511             :                    void *dst)
     512             : {
     513           0 :   struct TALER_DenominationSignature *sig = dst;
     514             :   size_t len;
     515             :   const char *res;
     516             :   int fnum;
     517             :   uint32_t be[2];
     518             : 
     519             :   (void) cls;
     520             :   (void) dst_size;
     521           0 :   fnum = PQfnumber (result,
     522             :                     fname);
     523           0 :   if (fnum < 0)
     524             :   {
     525           0 :     GNUNET_break (0);
     526           0 :     return GNUNET_SYSERR;
     527             :   }
     528           0 :   if (PQgetisnull (result,
     529             :                    row,
     530             :                    fnum))
     531           0 :     return GNUNET_NO;
     532             : 
     533             :   /* if a field is null, continue but
     534             :    * remember that we now return a different result */
     535           0 :   len = PQgetlength (result,
     536             :                      row,
     537             :                      fnum);
     538           0 :   res = PQgetvalue (result,
     539             :                     row,
     540             :                     fnum);
     541           0 :   if (len < sizeof (be))
     542             :   {
     543           0 :     GNUNET_break (0);
     544           0 :     return GNUNET_SYSERR;
     545             :   }
     546           0 :   memcpy (&be,
     547             :           res,
     548             :           sizeof (be));
     549           0 :   if (0x00 != ntohl (be[1]))
     550             :   {
     551           0 :     GNUNET_break (0);
     552           0 :     return GNUNET_SYSERR;
     553             :   }
     554           0 :   res += sizeof (be);
     555           0 :   len -= sizeof (be);
     556           0 :   sig->cipher = ntohl (be[0]);
     557           0 :   switch (sig->cipher)
     558             :   {
     559           0 :   case TALER_DENOMINATION_RSA:
     560             :     sig->details.rsa_signature
     561           0 :       = GNUNET_CRYPTO_rsa_signature_decode (res,
     562             :                                             len);
     563           0 :     if (NULL == sig->details.rsa_signature)
     564             :     {
     565           0 :       GNUNET_break (0);
     566           0 :       return GNUNET_SYSERR;
     567             :     }
     568           0 :     return GNUNET_OK;
     569           0 :   case TALER_DENOMINATION_CS:
     570           0 :     if (sizeof (sig->details.cs_signature) != len)
     571             :     {
     572           0 :       GNUNET_break (0);
     573           0 :       return GNUNET_SYSERR;
     574             :     }
     575           0 :     memcpy (&sig->details.cs_signature,
     576             :             res,
     577             :             len);
     578           0 :     return GNUNET_OK;
     579           0 :   default:
     580           0 :     GNUNET_break (0);
     581             :   }
     582           0 :   return GNUNET_SYSERR;
     583             : }
     584             : 
     585             : 
     586             : /**
     587             :  * Function called to clean up memory allocated
     588             :  * by a #GNUNET_PQ_ResultConverter.
     589             :  *
     590             :  * @param cls closure
     591             :  * @param rd result data to clean up
     592             :  */
     593             : static void
     594           0 : clean_denom_sig (void *cls,
     595             :                  void *rd)
     596             : {
     597           0 :   struct TALER_DenominationSignature *denom_sig = rd;
     598             : 
     599             :   (void) cls;
     600           0 :   TALER_denom_sig_free (denom_sig);
     601           0 : }
     602             : 
     603             : 
     604             : struct GNUNET_PQ_ResultSpec
     605           0 : TALER_PQ_result_spec_denom_sig (const char *name,
     606             :                                 struct TALER_DenominationSignature *denom_sig)
     607             : {
     608           0 :   struct GNUNET_PQ_ResultSpec res = {
     609             :     .conv = &extract_denom_sig,
     610             :     .cleaner = &clean_denom_sig,
     611             :     .dst = (void *) denom_sig,
     612             :     .fname = name
     613             :   };
     614             : 
     615           0 :   return res;
     616             : }
     617             : 
     618             : 
     619             : /**
     620             :  * Extract data from a Postgres database @a result at row @a row.
     621             :  *
     622             :  * @param cls closure
     623             :  * @param result where to extract data from
     624             :  * @param row the row to extract data from
     625             :  * @param fname name (or prefix) of the fields to extract from
     626             :  * @param[in,out] dst_size where to store size of result, may be NULL
     627             :  * @param[out] dst where to store the result
     628             :  * @return
     629             :  *   #GNUNET_YES if all results could be extracted
     630             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
     631             :  */
     632             : static enum GNUNET_GenericReturnValue
     633           0 : extract_blinded_denom_sig (void *cls,
     634             :                            PGresult *result,
     635             :                            int row,
     636             :                            const char *fname,
     637             :                            size_t *dst_size,
     638             :                            void *dst)
     639             : {
     640           0 :   struct TALER_BlindedDenominationSignature *sig = dst;
     641             :   size_t len;
     642             :   const char *res;
     643             :   int fnum;
     644             :   uint32_t be[2];
     645             : 
     646             :   (void) cls;
     647             :   (void) dst_size;
     648           0 :   fnum = PQfnumber (result,
     649             :                     fname);
     650           0 :   if (fnum < 0)
     651             :   {
     652           0 :     GNUNET_break (0);
     653           0 :     return GNUNET_SYSERR;
     654             :   }
     655           0 :   if (PQgetisnull (result,
     656             :                    row,
     657             :                    fnum))
     658           0 :     return GNUNET_NO;
     659             : 
     660             :   /* if a field is null, continue but
     661             :    * remember that we now return a different result */
     662           0 :   len = PQgetlength (result,
     663             :                      row,
     664             :                      fnum);
     665           0 :   res = PQgetvalue (result,
     666             :                     row,
     667             :                     fnum);
     668           0 :   if (len < sizeof (be))
     669             :   {
     670           0 :     GNUNET_break (0);
     671           0 :     return GNUNET_SYSERR;
     672             :   }
     673           0 :   memcpy (&be,
     674             :           res,
     675             :           sizeof (be));
     676           0 :   if (0x01 != ntohl (be[1])) /* magic marker: blinded */
     677             :   {
     678           0 :     GNUNET_break (0);
     679           0 :     return GNUNET_SYSERR;
     680             :   }
     681           0 :   res += sizeof (be);
     682           0 :   len -= sizeof (be);
     683           0 :   sig->cipher = ntohl (be[0]);
     684           0 :   switch (sig->cipher)
     685             :   {
     686           0 :   case TALER_DENOMINATION_RSA:
     687             :     sig->details.blinded_rsa_signature
     688           0 :       = GNUNET_CRYPTO_rsa_signature_decode (res,
     689             :                                             len);
     690           0 :     if (NULL == sig->details.blinded_rsa_signature)
     691             :     {
     692           0 :       GNUNET_break (0);
     693           0 :       return GNUNET_SYSERR;
     694             :     }
     695           0 :     return GNUNET_OK;
     696           0 :   case TALER_DENOMINATION_CS:
     697           0 :     if (sizeof (sig->details.blinded_cs_answer) != len)
     698             :     {
     699           0 :       GNUNET_break (0);
     700           0 :       return GNUNET_SYSERR;
     701             :     }
     702           0 :     memcpy (&sig->details.blinded_cs_answer,
     703             :             res,
     704             :             len);
     705           0 :     return GNUNET_OK;
     706           0 :   default:
     707           0 :     GNUNET_break (0);
     708             :   }
     709           0 :   return GNUNET_SYSERR;
     710             : }
     711             : 
     712             : 
     713             : /**
     714             :  * Function called to clean up memory allocated
     715             :  * by a #GNUNET_PQ_ResultConverter.
     716             :  *
     717             :  * @param cls closure
     718             :  * @param rd result data to clean up
     719             :  */
     720             : static void
     721           0 : clean_blinded_denom_sig (void *cls,
     722             :                          void *rd)
     723             : {
     724           0 :   struct TALER_BlindedDenominationSignature *denom_sig = rd;
     725             : 
     726             :   (void) cls;
     727           0 :   TALER_blinded_denom_sig_free (denom_sig);
     728           0 : }
     729             : 
     730             : 
     731             : struct GNUNET_PQ_ResultSpec
     732           0 : TALER_PQ_result_spec_blinded_denom_sig (
     733             :   const char *name,
     734             :   struct TALER_BlindedDenominationSignature *denom_sig)
     735             : {
     736           0 :   struct GNUNET_PQ_ResultSpec res = {
     737             :     .conv = &extract_blinded_denom_sig,
     738             :     .cleaner = &clean_blinded_denom_sig,
     739             :     .dst = (void *) denom_sig,
     740             :     .fname = name
     741             :   };
     742             : 
     743           0 :   return res;
     744             : }
     745             : 
     746             : 
     747             : /**
     748             :  * Extract data from a Postgres database @a result at row @a row.
     749             :  *
     750             :  * @param cls closure
     751             :  * @param result where to extract data from
     752             :  * @param row the row to extract data from
     753             :  * @param fname name (or prefix) of the fields to extract from
     754             :  * @param[in,out] dst_size where to store size of result, may be NULL
     755             :  * @param[out] dst where to store the result
     756             :  * @return
     757             :  *   #GNUNET_YES if all results could be extracted
     758             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
     759             :  */
     760             : static enum GNUNET_GenericReturnValue
     761           0 : extract_blinded_planchet (void *cls,
     762             :                           PGresult *result,
     763             :                           int row,
     764             :                           const char *fname,
     765             :                           size_t *dst_size,
     766             :                           void *dst)
     767             : {
     768           0 :   struct TALER_BlindedPlanchet *bp = dst;
     769             :   size_t len;
     770             :   const char *res;
     771             :   int fnum;
     772             :   uint32_t be[2];
     773             : 
     774             :   (void) cls;
     775             :   (void) dst_size;
     776           0 :   fnum = PQfnumber (result,
     777             :                     fname);
     778           0 :   if (fnum < 0)
     779             :   {
     780           0 :     GNUNET_break (0);
     781           0 :     return GNUNET_SYSERR;
     782             :   }
     783           0 :   if (PQgetisnull (result,
     784             :                    row,
     785             :                    fnum))
     786           0 :     return GNUNET_NO;
     787             : 
     788             :   /* if a field is null, continue but
     789             :    * remember that we now return a different result */
     790           0 :   len = PQgetlength (result,
     791             :                      row,
     792             :                      fnum);
     793           0 :   res = PQgetvalue (result,
     794             :                     row,
     795             :                     fnum);
     796           0 :   if (len < sizeof (be))
     797             :   {
     798           0 :     GNUNET_break (0);
     799           0 :     return GNUNET_SYSERR;
     800             :   }
     801           0 :   memcpy (&be,
     802             :           res,
     803             :           sizeof (be));
     804           0 :   if (0x0100 != ntohl (be[1])) /* magic marker: blinded */
     805             :   {
     806           0 :     GNUNET_break (0);
     807           0 :     return GNUNET_SYSERR;
     808             :   }
     809           0 :   res += sizeof (be);
     810           0 :   len -= sizeof (be);
     811           0 :   bp->cipher = ntohl (be[0]);
     812           0 :   switch (bp->cipher)
     813             :   {
     814           0 :   case TALER_DENOMINATION_RSA:
     815             :     bp->details.rsa_blinded_planchet.blinded_msg_size
     816           0 :       = len;
     817             :     bp->details.rsa_blinded_planchet.blinded_msg
     818           0 :       = GNUNET_memdup (res,
     819             :                        len);
     820           0 :     return GNUNET_OK;
     821           0 :   case TALER_DENOMINATION_CS:
     822           0 :     if (sizeof (bp->details.cs_blinded_planchet) != len)
     823             :     {
     824           0 :       GNUNET_break (0);
     825           0 :       return GNUNET_SYSERR;
     826             :     }
     827           0 :     memcpy (&bp->details.cs_blinded_planchet,
     828             :             res,
     829             :             len);
     830           0 :     return GNUNET_OK;
     831           0 :   default:
     832           0 :     GNUNET_break (0);
     833             :   }
     834           0 :   return GNUNET_SYSERR;
     835             : }
     836             : 
     837             : 
     838             : /**
     839             :  * Function called to clean up memory allocated
     840             :  * by a #GNUNET_PQ_ResultConverter.
     841             :  *
     842             :  * @param cls closure
     843             :  * @param rd result data to clean up
     844             :  */
     845             : static void
     846           0 : clean_blinded_planchet (void *cls,
     847             :                         void *rd)
     848             : {
     849           0 :   struct TALER_BlindedPlanchet *bp = rd;
     850             : 
     851             :   (void) cls;
     852           0 :   TALER_blinded_planchet_free (bp);
     853           0 : }
     854             : 
     855             : 
     856             : struct GNUNET_PQ_ResultSpec
     857           0 : TALER_PQ_result_spec_blinded_planchet (
     858             :   const char *name,
     859             :   struct TALER_BlindedPlanchet *bp)
     860             : {
     861           0 :   struct GNUNET_PQ_ResultSpec res = {
     862             :     .conv = &extract_blinded_planchet,
     863             :     .cleaner = &clean_blinded_planchet,
     864             :     .dst = (void *) bp,
     865             :     .fname = name
     866             :   };
     867             : 
     868           0 :   return res;
     869             : }
     870             : 
     871             : 
     872             : /**
     873             :  * Extract data from a Postgres database @a result at row @a row.
     874             :  *
     875             :  * @param cls closure
     876             :  * @param result where to extract data from
     877             :  * @param row row to extract data from
     878             :  * @param fname name (or prefix) of the fields to extract from
     879             :  * @param[in,out] dst_size where to store size of result, may be NULL
     880             :  * @param[out] dst where to store the result
     881             :  * @return
     882             :  *   #GNUNET_YES if all results could be extracted
     883             :  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
     884             :  */
     885             : static enum GNUNET_GenericReturnValue
     886           0 : extract_exchange_withdraw_values (void *cls,
     887             :                                   PGresult *result,
     888             :                                   int row,
     889             :                                   const char *fname,
     890             :                                   size_t *dst_size,
     891             :                                   void *dst)
     892             : {
     893           0 :   struct TALER_ExchangeWithdrawValues *alg_values = dst;
     894             :   size_t len;
     895             :   const char *res;
     896             :   int fnum;
     897             :   uint32_t be[2];
     898             : 
     899             :   (void) cls;
     900             :   (void) dst_size;
     901           0 :   fnum = PQfnumber (result,
     902             :                     fname);
     903           0 :   if (fnum < 0)
     904             :   {
     905           0 :     GNUNET_break (0);
     906           0 :     return GNUNET_SYSERR;
     907             :   }
     908           0 :   if (PQgetisnull (result,
     909             :                    row,
     910             :                    fnum))
     911           0 :     return GNUNET_NO;
     912             : 
     913             :   /* if a field is null, continue but
     914             :    * remember that we now return a different result */
     915           0 :   len = PQgetlength (result,
     916             :                      row,
     917             :                      fnum);
     918           0 :   res = PQgetvalue (result,
     919             :                     row,
     920             :                     fnum);
     921           0 :   if (len < sizeof (be))
     922             :   {
     923           0 :     GNUNET_break (0);
     924           0 :     return GNUNET_SYSERR;
     925             :   }
     926           0 :   memcpy (&be,
     927             :           res,
     928             :           sizeof (be));
     929           0 :   if (0x010000 != ntohl (be[1])) /* magic marker: EWV */
     930             :   {
     931           0 :     GNUNET_break (0);
     932           0 :     return GNUNET_SYSERR;
     933             :   }
     934           0 :   res += sizeof (be);
     935           0 :   len -= sizeof (be);
     936           0 :   alg_values->cipher = ntohl (be[0]);
     937           0 :   switch (alg_values->cipher)
     938             :   {
     939           0 :   case TALER_DENOMINATION_RSA:
     940           0 :     if (0 != len)
     941             :     {
     942           0 :       GNUNET_break (0);
     943           0 :       return GNUNET_SYSERR;
     944             :     }
     945           0 :     return GNUNET_OK;
     946           0 :   case TALER_DENOMINATION_CS:
     947           0 :     if (sizeof (struct TALER_DenominationCSPublicRPairP) != len)
     948             :     {
     949           0 :       GNUNET_break (0);
     950           0 :       return GNUNET_SYSERR;
     951             :     }
     952           0 :     memcpy (&alg_values->details.cs_values,
     953             :             res,
     954             :             len);
     955           0 :     return GNUNET_OK;
     956           0 :   default:
     957           0 :     GNUNET_break (0);
     958             :   }
     959           0 :   return GNUNET_SYSERR;
     960             : }
     961             : 
     962             : 
     963             : struct GNUNET_PQ_ResultSpec
     964           0 : TALER_PQ_result_spec_exchange_withdraw_values (
     965             :   const char *name,
     966             :   struct TALER_ExchangeWithdrawValues *ewv)
     967             : {
     968           0 :   struct GNUNET_PQ_ResultSpec res = {
     969             :     .conv = &extract_exchange_withdraw_values,
     970             :     .dst = (void *) ewv,
     971             :     .fname = name
     972             :   };
     973             : 
     974           0 :   return res;
     975             : }
     976             : 
     977             : 
     978             : /* end of pq_result_helper.c */

Generated by: LCOV version 1.14