exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

util.c (9595B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file util.c
     18  * @brief Common utility functions
     19  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
     20  * @author Florian Dold
     21  * @author Benedikt Mueller
     22  * @author Christian Grothoff
     23  */
     24 #include "platform.h"
     25 #include "taler/taler_util.h"
     26 #include <gnunet/gnunet_json_lib.h>
     27 #include <unistr.h>
     28 
     29 
     30 const char *
     31 TALER_b2s (const void *buf,
     32            size_t buf_size)
     33 {
     34   static TALER_THREAD_LOCAL char ret[9];
     35   struct GNUNET_HashCode hc;
     36   char *tmp;
     37 
     38   GNUNET_CRYPTO_hash (buf,
     39                       buf_size,
     40                       &hc);
     41   tmp = GNUNET_STRINGS_data_to_string_alloc (&hc,
     42                                              sizeof (hc));
     43   GNUNET_memcpy (ret,
     44                  tmp,
     45                  8);
     46   GNUNET_free (tmp);
     47   ret[8] = '\0';
     48   return ret;
     49 }
     50 
     51 
     52 void
     53 TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
     54                           const struct TALER_DenomFeeSet *fees)
     55 {
     56   TALER_amount_hton (&nbo->withdraw,
     57                      &fees->withdraw);
     58   TALER_amount_hton (&nbo->deposit,
     59                      &fees->deposit);
     60   TALER_amount_hton (&nbo->refresh,
     61                      &fees->refresh);
     62   TALER_amount_hton (&nbo->refund,
     63                      &fees->refund);
     64 }
     65 
     66 
     67 void
     68 TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
     69                           const struct TALER_DenomFeeSetNBOP *nbo)
     70 {
     71   TALER_amount_ntoh (&fees->withdraw,
     72                      &nbo->withdraw);
     73   TALER_amount_ntoh (&fees->deposit,
     74                      &nbo->deposit);
     75   TALER_amount_ntoh (&fees->refresh,
     76                      &nbo->refresh);
     77   TALER_amount_ntoh (&fees->refund,
     78                      &nbo->refund);
     79 }
     80 
     81 
     82 void
     83 TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo,
     84                            const struct TALER_GlobalFeeSet *fees)
     85 {
     86   TALER_amount_hton (&nbo->history,
     87                      &fees->history);
     88   TALER_amount_hton (&nbo->account,
     89                      &fees->account);
     90   TALER_amount_hton (&nbo->purse,
     91                      &fees->purse);
     92 }
     93 
     94 
     95 void
     96 TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees,
     97                            const struct TALER_GlobalFeeSetNBOP *nbo)
     98 {
     99   TALER_amount_ntoh (&fees->history,
    100                      &nbo->history);
    101   TALER_amount_ntoh (&fees->account,
    102                      &nbo->account);
    103   TALER_amount_ntoh (&fees->purse,
    104                      &nbo->purse);
    105 }
    106 
    107 
    108 void
    109 TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo,
    110                          const struct TALER_WireFeeSet *fees)
    111 {
    112   TALER_amount_hton (&nbo->wire,
    113                      &fees->wire);
    114   TALER_amount_hton (&nbo->closing,
    115                      &fees->closing);
    116 }
    117 
    118 
    119 void
    120 TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees,
    121                          const struct TALER_WireFeeSetNBOP *nbo)
    122 {
    123   TALER_amount_ntoh (&fees->wire,
    124                      &nbo->wire);
    125   TALER_amount_ntoh (&fees->closing,
    126                      &nbo->closing);
    127 }
    128 
    129 
    130 int
    131 TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1,
    132                           const struct TALER_GlobalFeeSet *f2)
    133 {
    134   int ret;
    135 
    136   ret = TALER_amount_cmp (&f1->history,
    137                           &f2->history);
    138   if (0 != ret)
    139     return ret;
    140   ret = TALER_amount_cmp (&f1->account,
    141                           &f2->account);
    142   if (0 != ret)
    143     return ret;
    144   ret = TALER_amount_cmp (&f1->purse,
    145                           &f2->purse);
    146   if (0 != ret)
    147     return ret;
    148   return 0;
    149 }
    150 
    151 
    152 int
    153 TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1,
    154                         const struct TALER_WireFeeSet *f2)
    155 {
    156   int ret;
    157 
    158   ret = TALER_amount_cmp (&f1->wire,
    159                           &f2->wire);
    160   if (0 != ret)
    161     return ret;
    162   ret = TALER_amount_cmp (&f1->closing,
    163                           &f2->closing);
    164   if (0 != ret)
    165     return ret;
    166   return 0;
    167 }
    168 
    169 
    170 enum GNUNET_GenericReturnValue
    171 TALER_denom_fee_check_currency (
    172   const char *currency,
    173   const struct TALER_DenomFeeSet *fees)
    174 {
    175   if (GNUNET_YES !=
    176       TALER_amount_is_currency (&fees->withdraw,
    177                                 currency))
    178   {
    179     GNUNET_break (0);
    180     return GNUNET_NO;
    181   }
    182   if (GNUNET_YES !=
    183       TALER_amount_is_currency (&fees->deposit,
    184                                 currency))
    185   {
    186     GNUNET_break (0);
    187     return GNUNET_NO;
    188   }
    189   if (GNUNET_YES !=
    190       TALER_amount_is_currency (&fees->refresh,
    191                                 currency))
    192   {
    193     GNUNET_break (0);
    194     return GNUNET_NO;
    195   }
    196   if (GNUNET_YES !=
    197       TALER_amount_is_currency (&fees->refund,
    198                                 currency))
    199   {
    200     GNUNET_break (0);
    201     return GNUNET_NO;
    202   }
    203   return GNUNET_OK;
    204 }
    205 
    206 
    207 /**
    208  * Dump character in the low range into @a buf
    209  * following RFC 8785.
    210  *
    211  * @param[in,out] buf buffer to modify
    212  * @param val value to dump
    213  */
    214 static void
    215 lowdump (struct GNUNET_Buffer *buf,
    216          unsigned char val)
    217 {
    218   char scratch[7];
    219 
    220   switch (val)
    221   {
    222   case 0x8:
    223     GNUNET_buffer_write (buf,
    224                          "\\b",
    225                          2);
    226     break;
    227   case 0x9:
    228     GNUNET_buffer_write (buf,
    229                          "\\t",
    230                          2);
    231     break;
    232   case 0xA:
    233     GNUNET_buffer_write (buf,
    234                          "\\n",
    235                          2);
    236     break;
    237   case 0xC:
    238     GNUNET_buffer_write (buf,
    239                          "\\f",
    240                          2);
    241     break;
    242   case 0xD:
    243     GNUNET_buffer_write (buf,
    244                          "\\r",
    245                          2);
    246     break;
    247   default:
    248     GNUNET_snprintf (scratch,
    249                      sizeof (scratch),
    250                      "\\u%04x",
    251                      (unsigned int) val);
    252     GNUNET_buffer_write (buf,
    253                          scratch,
    254                          6);
    255     break;
    256   }
    257 }
    258 
    259 
    260 size_t
    261 TALER_rfc8785encode (char **inp)
    262 {
    263   struct GNUNET_Buffer buf = { 0 };
    264   size_t left = strlen (*inp) + 1;
    265   size_t olen;
    266   char *in = *inp;
    267   const char *pos = in;
    268 
    269   GNUNET_buffer_prealloc (&buf,
    270                           left + 40);
    271   buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
    272   while (1)
    273   {
    274     int mbl = u8_mblen ((unsigned char *) pos,
    275                         left);
    276     unsigned char val;
    277 
    278     if (0 == mbl)
    279       break;
    280     val = (unsigned char) *pos;
    281     if ( (1 == mbl) &&
    282          (val <= 0x1F) )
    283     {
    284       /* Should not happen, as input is produced by
    285        * JSON stringification */
    286       GNUNET_break (0);
    287       lowdump (&buf,
    288                val);
    289     }
    290     else if ( (1 == mbl) && ('\\' == *pos) )
    291     {
    292       switch (*(pos + 1))
    293       {
    294       case '\\':
    295         mbl = 2;
    296         GNUNET_buffer_write (&buf,
    297                              pos,
    298                              mbl);
    299         break;
    300       case 'u':
    301         {
    302           unsigned int num;
    303           uint32_t n32;
    304           unsigned char res[8];
    305           size_t rlen;
    306 
    307           GNUNET_assert ( (1 ==
    308                            sscanf (pos + 2,
    309                                    "%4x",
    310                                    &num)) ||
    311                           (1 ==
    312                            sscanf (pos + 2,
    313                                    "%4X",
    314                                    &num)) );
    315           mbl = 6;
    316           n32 = (uint32_t) num;
    317           rlen = sizeof (res);
    318           u32_to_u8 (&n32,
    319                      1,
    320                      res,
    321                      &rlen);
    322           if ( (1 == rlen) &&
    323                (res[0] <= 0x1F) )
    324           {
    325             lowdump (&buf,
    326                      res[0]);
    327           }
    328           else
    329           {
    330             GNUNET_buffer_write (&buf,
    331                                  (const char *) res,
    332                                  rlen);
    333           }
    334         }
    335         break;
    336       default:
    337         mbl = 2;
    338         GNUNET_buffer_write (&buf,
    339                              pos,
    340                              mbl);
    341         break;
    342       }
    343     }
    344     else
    345     {
    346       GNUNET_buffer_write (&buf,
    347                            pos,
    348                            mbl);
    349     }
    350     left -= mbl;
    351     pos += mbl;
    352   }
    353 
    354   /* 0-terminate buffer */
    355   GNUNET_buffer_write (&buf,
    356                        "",
    357                        1);
    358   GNUNET_free (in);
    359   *inp = GNUNET_buffer_reap (&buf,
    360                              &olen);
    361   return olen;
    362 }
    363 
    364 
    365 /**
    366  * Hash normalized @a j JSON object or array and
    367  * store the result in @a hc.
    368  *
    369  * @param j JSON to hash
    370  * @param[out] hc where to write the hash
    371  */
    372 void
    373 TALER_json_hash (const json_t *j,
    374                  struct GNUNET_HashCode *hc)
    375 {
    376   char *cstr;
    377   size_t clen;
    378 
    379   cstr = json_dumps (j,
    380                      JSON_COMPACT | JSON_SORT_KEYS);
    381   GNUNET_assert (NULL != cstr);
    382   clen = TALER_rfc8785encode (&cstr);
    383   GNUNET_CRYPTO_hash (cstr,
    384                       clen,
    385                       hc);
    386   GNUNET_free (cstr);
    387 }
    388 
    389 
    390 #ifdef __APPLE__
    391 char *
    392 strchrnul (const char *s,
    393            int c)
    394 {
    395   char *value;
    396   value = strchr (s,
    397                   c);
    398   if (NULL == value)
    399     value = &s[strlen (s)];
    400   return value;
    401 }
    402 
    403 
    404 #endif
    405 
    406 
    407 /* end of util.c */