exchange

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

util.c (9637B)


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