LCOV - code coverage report
Current view: top level - util - util.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.3 % 179 124
Test Date: 2026-05-12 15:34:29 Functions: 73.3 % 15 11

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2014-2023 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify it under the
       6              :   terms of the GNU General Public License as published by the Free Software
       7              :   Foundation; either version 3, or (at your option) any later version.
       8              : 
       9              :   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10              :   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11              :   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12              : 
      13              :   You should have received a copy of the GNU General Public License along with
      14              :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15              : */
      16              : /**
      17              :  * @file 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         2514 : 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         2514 :   GNUNET_CRYPTO_hash (buf,
      39              :                       buf_size,
      40              :                       &hc);
      41         2514 :   tmp = GNUNET_STRINGS_data_to_string_alloc (&hc,
      42              :                                              sizeof (hc));
      43         2514 :   GNUNET_memcpy (ret,
      44              :                  tmp,
      45              :                  8);
      46         2514 :   GNUNET_free (tmp);
      47         2514 :   ret[8] = '\0';
      48         2514 :   return ret;
      49              : }
      50              : 
      51              : 
      52              : void
      53         3925 : TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
      54              :                           const struct TALER_DenomFeeSet *fees)
      55              : {
      56         3925 :   TALER_amount_hton (&nbo->withdraw,
      57              :                      &fees->withdraw);
      58         3925 :   TALER_amount_hton (&nbo->deposit,
      59              :                      &fees->deposit);
      60         3925 :   TALER_amount_hton (&nbo->refresh,
      61              :                      &fees->refresh);
      62         3925 :   TALER_amount_hton (&nbo->refund,
      63              :                      &fees->refund);
      64         3925 : }
      65              : 
      66              : 
      67              : void
      68            0 : TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
      69              :                           const struct TALER_DenomFeeSetNBOP *nbo)
      70              : {
      71            0 :   TALER_amount_ntoh (&fees->withdraw,
      72              :                      &nbo->withdraw);
      73            0 :   TALER_amount_ntoh (&fees->deposit,
      74              :                      &nbo->deposit);
      75            0 :   TALER_amount_ntoh (&fees->refresh,
      76              :                      &nbo->refresh);
      77            0 :   TALER_amount_ntoh (&fees->refund,
      78              :                      &nbo->refund);
      79            0 : }
      80              : 
      81              : 
      82              : void
      83          184 : TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo,
      84              :                            const struct TALER_GlobalFeeSet *fees)
      85              : {
      86          184 :   TALER_amount_hton (&nbo->history,
      87              :                      &fees->history);
      88          184 :   TALER_amount_hton (&nbo->account,
      89              :                      &fees->account);
      90          184 :   TALER_amount_hton (&nbo->purse,
      91              :                      &fees->purse);
      92          184 : }
      93              : 
      94              : 
      95              : void
      96            0 : TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees,
      97              :                            const struct TALER_GlobalFeeSetNBOP *nbo)
      98              : {
      99            0 :   TALER_amount_ntoh (&fees->history,
     100              :                      &nbo->history);
     101            0 :   TALER_amount_ntoh (&fees->account,
     102              :                      &nbo->account);
     103            0 :   TALER_amount_ntoh (&fees->purse,
     104              :                      &nbo->purse);
     105            0 : }
     106              : 
     107              : 
     108              : void
     109          208 : TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo,
     110              :                          const struct TALER_WireFeeSet *fees)
     111              : {
     112          208 :   TALER_amount_hton (&nbo->wire,
     113              :                      &fees->wire);
     114          208 :   TALER_amount_hton (&nbo->closing,
     115              :                      &fees->closing);
     116          208 : }
     117              : 
     118              : 
     119              : void
     120            0 : TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees,
     121              :                          const struct TALER_WireFeeSetNBOP *nbo)
     122              : {
     123            0 :   TALER_amount_ntoh (&fees->wire,
     124              :                      &nbo->wire);
     125            0 :   TALER_amount_ntoh (&fees->closing,
     126              :                      &nbo->closing);
     127            0 : }
     128              : 
     129              : 
     130              : int
     131            0 : TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1,
     132              :                           const struct TALER_GlobalFeeSet *f2)
     133              : {
     134              :   int ret;
     135              : 
     136            0 :   ret = TALER_amount_cmp (&f1->history,
     137              :                           &f2->history);
     138            0 :   if (0 != ret)
     139            0 :     return ret;
     140            0 :   ret = TALER_amount_cmp (&f1->account,
     141              :                           &f2->account);
     142            0 :   if (0 != ret)
     143            0 :     return ret;
     144            0 :   ret = TALER_amount_cmp (&f1->purse,
     145              :                           &f2->purse);
     146            0 :   if (0 != ret)
     147            0 :     return ret;
     148            0 :   return 0;
     149              : }
     150              : 
     151              : 
     152              : int
     153            4 : TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1,
     154              :                         const struct TALER_WireFeeSet *f2)
     155              : {
     156              :   int ret;
     157              : 
     158            4 :   ret = TALER_amount_cmp (&f1->wire,
     159              :                           &f2->wire);
     160            4 :   if (0 != ret)
     161            0 :     return ret;
     162            4 :   ret = TALER_amount_cmp (&f1->closing,
     163              :                           &f2->closing);
     164            4 :   if (0 != ret)
     165            2 :     return ret;
     166            2 :   return 0;
     167              : }
     168              : 
     169              : 
     170              : enum GNUNET_GenericReturnValue
     171         1419 : TALER_denom_fee_check_currency (
     172              :   const char *currency,
     173              :   const struct TALER_DenomFeeSet *fees)
     174              : {
     175         1419 :   if (GNUNET_YES !=
     176         1419 :       TALER_amount_is_currency (&fees->withdraw,
     177              :                                 currency))
     178              :   {
     179            0 :     GNUNET_break (0);
     180            0 :     return GNUNET_NO;
     181              :   }
     182         1419 :   if (GNUNET_YES !=
     183         1419 :       TALER_amount_is_currency (&fees->deposit,
     184              :                                 currency))
     185              :   {
     186            0 :     GNUNET_break (0);
     187            0 :     return GNUNET_NO;
     188              :   }
     189         1419 :   if (GNUNET_YES !=
     190         1419 :       TALER_amount_is_currency (&fees->refresh,
     191              :                                 currency))
     192              :   {
     193            0 :     GNUNET_break (0);
     194            0 :     return GNUNET_NO;
     195              :   }
     196         1419 :   if (GNUNET_YES !=
     197         1419 :       TALER_amount_is_currency (&fees->refund,
     198              :                                 currency))
     199              :   {
     200            0 :     GNUNET_break (0);
     201            0 :     return GNUNET_NO;
     202              :   }
     203         1419 :   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            3 : lowdump (struct GNUNET_Buffer *buf,
     216              :          unsigned char val)
     217              : {
     218              :   char scratch[7];
     219              : 
     220            3 :   switch (val)
     221              :   {
     222            0 :   case 0x8:
     223            0 :     GNUNET_buffer_write (buf,
     224              :                          "\\b",
     225              :                          2);
     226            0 :     break;
     227            0 :   case 0x9:
     228            0 :     GNUNET_buffer_write (buf,
     229              :                          "\\t",
     230              :                          2);
     231            0 :     break;
     232            0 :   case 0xA:
     233            0 :     GNUNET_buffer_write (buf,
     234              :                          "\\n",
     235              :                          2);
     236            0 :     break;
     237            0 :   case 0xC:
     238            0 :     GNUNET_buffer_write (buf,
     239              :                          "\\f",
     240              :                          2);
     241            0 :     break;
     242            0 :   case 0xD:
     243            0 :     GNUNET_buffer_write (buf,
     244              :                          "\\r",
     245              :                          2);
     246            0 :     break;
     247            3 :   default:
     248            3 :     GNUNET_snprintf (scratch,
     249              :                      sizeof (scratch),
     250              :                      "\\u%04x",
     251              :                      (unsigned int) val);
     252            3 :     GNUNET_buffer_write (buf,
     253              :                          scratch,
     254              :                          6);
     255            3 :     break;
     256              :   }
     257            3 : }
     258              : 
     259              : 
     260              : size_t
     261          617 : TALER_rfc8785encode (char **inp)
     262              : {
     263          617 :   struct GNUNET_Buffer buf = { 0 };
     264          617 :   size_t left = strlen (*inp) + 1;
     265              :   size_t olen;
     266          617 :   char *in = *inp;
     267          617 :   const char *pos = in;
     268              : 
     269          617 :   GNUNET_buffer_prealloc (&buf,
     270              :                           left + 40);
     271          617 :   buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
     272              :   while (1)
     273        17353 :   {
     274        17970 :     int mbl = u8_mblen ((unsigned char *) pos,
     275              :                         left);
     276              :     unsigned char val;
     277              : 
     278        17970 :     if (0 == mbl)
     279          617 :       break;
     280        17353 :     val = (unsigned char) *pos;
     281        17353 :     if ( (1 == mbl) &&
     282              :          (val <= 0x1F) )
     283              :     {
     284              :       /* Should not happen, as input is produced by
     285              :        * JSON stringification */
     286            0 :       GNUNET_break (0);
     287            0 :       lowdump (&buf,
     288              :                val);
     289              :     }
     290        17353 :     else if ( (1 == mbl) && ('\\' == *pos) )
     291              :     {
     292            8 :       switch (*(pos + 1))
     293              :       {
     294            1 :       case '\\':
     295            1 :         mbl = 2;
     296            1 :         GNUNET_buffer_write (&buf,
     297              :                              pos,
     298              :                              mbl);
     299            1 :         break;
     300            3 :       case 'u':
     301              :         {
     302              :           unsigned int num;
     303              :           uint32_t n32;
     304              :           unsigned char res[8];
     305              :           size_t rlen;
     306              : 
     307            3 :           GNUNET_assert ( (1 ==
     308              :                            sscanf (pos + 2,
     309              :                                    "%4x",
     310              :                                    &num)) ||
     311              :                           (1 ==
     312              :                            sscanf (pos + 2,
     313              :                                    "%4X",
     314              :                                    &num)) );
     315            3 :           mbl = 6;
     316            3 :           n32 = (uint32_t) num;
     317            3 :           rlen = sizeof (res);
     318            3 :           u32_to_u8 (&n32,
     319              :                      1,
     320              :                      res,
     321              :                      &rlen);
     322            3 :           if ( (1 == rlen) &&
     323            3 :                (res[0] <= 0x1F) )
     324              :           {
     325            3 :             lowdump (&buf,
     326            3 :                      res[0]);
     327              :           }
     328              :           else
     329              :           {
     330            0 :             GNUNET_buffer_write (&buf,
     331              :                                  (const char *) res,
     332              :                                  rlen);
     333              :           }
     334              :         }
     335            3 :         break;
     336            4 :       default:
     337            4 :         mbl = 2;
     338            4 :         GNUNET_buffer_write (&buf,
     339              :                              pos,
     340              :                              mbl);
     341            4 :         break;
     342              :       }
     343              :     }
     344              :     else
     345              :     {
     346        17345 :       GNUNET_buffer_write (&buf,
     347              :                            pos,
     348              :                            mbl);
     349              :     }
     350        17353 :     left -= mbl;
     351        17353 :     pos += mbl;
     352              :   }
     353              : 
     354              :   /* 0-terminate buffer */
     355          617 :   GNUNET_buffer_write (&buf,
     356              :                        "",
     357              :                        1);
     358          617 :   GNUNET_free (in);
     359          617 :   *inp = GNUNET_buffer_reap (&buf,
     360              :                              &olen);
     361          617 :   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          436 : TALER_json_hash (const json_t *j,
     374              :                  struct GNUNET_HashCode *hc)
     375              : {
     376              :   char *cstr;
     377              :   size_t clen;
     378              : 
     379          436 :   cstr = json_dumps (j,
     380              :                      JSON_COMPACT | JSON_SORT_KEYS);
     381          436 :   GNUNET_assert (NULL != cstr);
     382          436 :   clen = TALER_rfc8785encode (&cstr);
     383          436 :   GNUNET_CRYPTO_hash (cstr,
     384              :                       clen,
     385              :                       hc);
     386          436 :   GNUNET_free (cstr);
     387          436 : }
     388              : 
     389              : 
     390              : char **
     391          370 : TALER_words_split (const char *command,
     392              :                    const char **extra_args)
     393              : {
     394          370 :   unsigned int i = 0;
     395          370 :   unsigned int j = 0;
     396          370 :   unsigned int n = 0;
     397          370 :   char **res = NULL;
     398              : 
     399              :   /* Result is always NULL-terminated */
     400          370 :   GNUNET_array_append (res, n, NULL);
     401              : 
     402              :   /* Split command into words */
     403              :   while (1)
     404          370 :   {
     405              :     char *c;
     406              : 
     407              :     /* Skip initial whitespace before word */
     408          740 :     while (' ' == command[i])
     409            0 :       i++;
     410              : 
     411              :     /* Start of new word */
     412          740 :     j = i;
     413              : 
     414              :     /* Scan to end of word */
     415        14558 :     while ( (0 != command[j]) && (' ' != command[j]) )
     416        13818 :       j++;
     417              : 
     418              :     /* No new word found */
     419          740 :     if (i == j)
     420          370 :       break;
     421              : 
     422              :     /* Append word to result */
     423          370 :     c = GNUNET_malloc (j - i + 1);
     424          370 :     memcpy (c, &command[i], j - i);
     425          370 :     c[j - i] = 0;
     426          370 :     res[n - 1] = c;
     427          370 :     GNUNET_array_append (res, n, NULL);
     428              : 
     429              :     /* Continue at end of word */
     430          370 :     i = j;
     431              :   }
     432              : 
     433              :   /* Append extra args */
     434          370 :   if (NULL != extra_args)
     435              :   {
     436         1470 :     for (const char **m = extra_args; *m; m++)
     437              :     {
     438         1100 :       res[n - 1] = GNUNET_strdup (*m);
     439         1100 :       GNUNET_array_append (res,
     440              :                            n,
     441              :                            NULL);
     442              :     }
     443              :   }
     444              : 
     445          370 :   return res;
     446              : }
     447              : 
     448              : 
     449              : void
     450           10 : TALER_words_destroy (char **args)
     451              : {
     452           10 :   if (NULL == args)
     453            0 :     return;
     454           40 :   for (char **m = args; *m; m++)
     455              :   {
     456           30 :     GNUNET_free (*m);
     457           30 :     *m = NULL;
     458              :   }
     459           10 :   GNUNET_free (args);
     460              : }
     461              : 
     462              : 
     463              : #ifdef __APPLE__
     464              : char *
     465              : strchrnul (const char *s,
     466              :            int c)
     467              : {
     468              :   char *value;
     469              :   value = strchr (s,
     470              :                   c);
     471              :   if (NULL == value)
     472              :     value = &s[strlen (s)];
     473              :   return value;
     474              : }
     475              : 
     476              : 
     477              : #endif
     478              : 
     479              : 
     480              : /* end of util.c */
        

Generated by: LCOV version 2.0-1