LCOV - code coverage report
Current view: top level - util - util.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.2 % 96 78
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2026 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify it under the
       6              :   terms of the GNU Lesser 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 src/util/util.c
      18              :  * @brief small helpers
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "platform.h"
      22              : #include <string.h>
      23              : #include "taler/taler_merchant_util.h"
      24              : #include <taler/taler_json_lib.h>
      25              : #include <gnunet/gnunet_json_lib.h>
      26              : 
      27              : 
      28              : bool
      29          119 : TALER_MERCHANT_taxes_array_valid (const json_t *taxes)
      30              : {
      31              :   json_t *tax;
      32              :   size_t idx;
      33              : 
      34          119 :   if (! json_is_array (taxes))
      35            0 :     return false;
      36          119 :   json_array_foreach (taxes, idx, tax)
      37              :   {
      38              :     struct TALER_Amount amount;
      39              :     const char *name;
      40              :     struct GNUNET_JSON_Specification spec[] = {
      41            0 :       GNUNET_JSON_spec_string ("name",
      42              :                                &name),
      43            0 :       TALER_JSON_spec_amount_any ("tax",
      44              :                                   &amount),
      45            0 :       GNUNET_JSON_spec_end ()
      46              :     };
      47              :     enum GNUNET_GenericReturnValue res;
      48              :     const char *ename;
      49              :     unsigned int eline;
      50              : 
      51            0 :     res = GNUNET_JSON_parse (tax,
      52              :                              spec,
      53              :                              &ename,
      54              :                              &eline);
      55            0 :     if (GNUNET_OK != res)
      56              :     {
      57            0 :       GNUNET_break_op (0);
      58            0 :       return false;
      59              :     }
      60              :   }
      61          119 :   return true;
      62              : }
      63              : 
      64              : 
      65              : bool
      66           63 : TALER_MERCHANT_payment_method_valid (
      67              :   const char *method)
      68              : {
      69           63 :   if ( (0 == strlen (method)) ||
      70           62 :        (0 == strcasecmp ("taler",
      71              :                          method)) )
      72              :   {
      73            6 :     GNUNET_break_op (0);
      74            6 :     return false;
      75              :   }
      76          283 :   for (const char *c = method; '\0' != *c; c++)
      77          227 :     if ( (! isalnum ((unsigned char) *c)) &&
      78            1 :          ('-' != *c) )
      79              :     {
      80            1 :       GNUNET_break_op (0);
      81            1 :       return false;
      82              :     }
      83           56 :   return true;
      84              : }
      85              : 
      86              : 
      87              : bool
      88           33 : TALER_MERCHANT_amount_external_valid (
      89              :   const json_t *amount_external)
      90              : {
      91              :   struct TALER_Amount first;
      92           33 :   bool have_first = false;
      93              :   json_t *entry;
      94              :   size_t idx;
      95              : 
      96           33 :   if (! json_is_array (amount_external))
      97            0 :     return false;
      98           58 :   json_array_foreach (amount_external, idx, entry)
      99              :   {
     100              :     const char *method;
     101              :     const char *id;
     102              :     struct TALER_Amount ext_amount;
     103              :     struct GNUNET_JSON_Specification spec[] = {
     104           37 :       GNUNET_JSON_spec_string ("method",
     105              :                                &method),
     106           37 :       GNUNET_JSON_spec_string ("id",
     107              :                                &id),
     108           37 :       TALER_JSON_spec_amount_any ("amount",
     109              :                                   &ext_amount),
     110           37 :       GNUNET_JSON_spec_end ()
     111              :     };
     112              : 
     113           37 :     if (GNUNET_OK !=
     114           37 :         GNUNET_JSON_parse (entry,
     115              :                            spec,
     116              :                            NULL,
     117              :                            NULL))
     118              :     {
     119            2 :       GNUNET_break_op (0);
     120           12 :       return false;
     121              :     }
     122           35 :     if (! TALER_MERCHANT_payment_method_valid (method))
     123            5 :       return false;
     124           30 :     if (0 == strlen (id))
     125              :     {
     126            0 :       GNUNET_break_op (0);
     127            0 :       return false;
     128              :     }
     129           30 :     if (! have_first)
     130              :     {
     131           26 :       first = ext_amount;
     132           26 :       have_first = true;
     133              :     }
     134            4 :     else if (GNUNET_OK !=
     135            4 :              TALER_amount_cmp_currency (&ext_amount,
     136              :                                         &first))
     137              :     {
     138              :       /* the entries have to agree on a currency among themselves */
     139            1 :       GNUNET_break_op (0);
     140            1 :       return false;
     141              :     }
     142           31 :     for (size_t j = 0; j < idx; j++)
     143              :     {
     144              :       const char *other_id
     145            3 :         = json_string_value (
     146            3 :             json_object_get (json_array_get (amount_external,
     147              :                                              j),
     148              :                              "id"));
     149              : 
     150            3 :       if ( (NULL != other_id) &&
     151            3 :            (0 == strcmp (id,
     152              :                          other_id)) )
     153              :       {
     154            1 :         GNUNET_break_op (0);
     155            1 :         return false;
     156              :       }
     157              :     }
     158              :     {
     159              :       const char *key;
     160              :       json_t *value;
     161              : 
     162          118 :       json_object_foreach (entry, key, value)
     163              :       {
     164           93 :         if ( (json_is_object (value)) ||
     165           90 :              (json_is_array (value)) ||
     166           90 :              (json_is_real (value)) )
     167              :         {
     168            3 :           GNUNET_break_op (0);
     169            3 :           return false;
     170              :         }
     171              :       }
     172              :     }
     173              :   }
     174           21 :   return true;
     175              : }
     176              : 
     177              : 
     178              : bool
     179           22 : TALER_MERCHANT_amount_external_currency_valid (
     180              :   const json_t *amount_external,
     181              :   const struct TALER_Amount *amount)
     182              : {
     183              :   struct TALER_Amount ext_amount;
     184              :   struct GNUNET_JSON_Specification spec[] = {
     185           22 :     TALER_JSON_spec_amount_any ("amount",
     186              :                                 &ext_amount),
     187           22 :     GNUNET_JSON_spec_end ()
     188              :   };
     189              : 
     190           22 :   if (0 == json_array_size (amount_external))
     191            0 :     return true; /* no external payment to agree with */
     192           22 :   if (GNUNET_OK !=
     193           22 :       GNUNET_JSON_parse (json_array_get (amount_external,
     194              :                                          0),
     195              :                          spec,
     196              :                          NULL,
     197              :                          NULL))
     198              :   {
     199            0 :     GNUNET_break_op (0);
     200            0 :     return false;
     201              :   }
     202           22 :   return (GNUNET_OK ==
     203           22 :           TALER_amount_cmp_currency (&ext_amount,
     204              :                                      amount));
     205              : }
     206              : 
     207              : 
     208              : bool
     209           19 : TALER_MERCHANT_amount_external_total_valid (
     210              :   const json_t *amount_external,
     211              :   const struct TALER_Amount *amount)
     212              : {
     213           19 :   struct TALER_Amount total = *amount;
     214              :   json_t *entry;
     215              :   size_t idx;
     216              : 
     217           37 :   json_array_foreach ((json_t *) amount_external, idx, entry)
     218              :   {
     219              :     struct TALER_Amount ext_amount;
     220              :     struct GNUNET_JSON_Specification spec[] = {
     221           20 :       TALER_JSON_spec_amount_any ("amount",
     222              :                                   &ext_amount),
     223           20 :       GNUNET_JSON_spec_end ()
     224              :     };
     225              : 
     226           20 :     if (GNUNET_OK !=
     227           20 :         GNUNET_JSON_parse (entry,
     228              :                            spec,
     229              :                            NULL,
     230              :                            NULL))
     231              :     {
     232            0 :       GNUNET_break_op (0);
     233            2 :       return false;
     234              :     }
     235           20 :     if (0 >
     236           20 :         TALER_amount_add (&total,
     237              :                           &total,
     238              :                           &ext_amount))
     239              :     {
     240              :       /* The order total would not be representable; refusing here
     241              :          keeps us from storing an order whose total can never be
     242              :          computed again. */
     243            2 :       GNUNET_break_op (0);
     244            2 :       return false;
     245              :     }
     246              :   }
     247           17 :   return true;
     248              : }
     249              : 
     250              : 
     251              : enum TALER_MERCHANT_ContractTokenKind
     252           11 : TALER_MERCHANT_contract_token_kind_from_string (const char *str)
     253              : {
     254           11 :   if (NULL == str)
     255              :   {
     256            0 :     GNUNET_break (0);
     257            0 :     return TALER_MERCHANT_CONTRACT_TOKEN_KIND_INVALID;
     258              :   }
     259           11 :   if (0 == strcmp ("subscription",
     260              :                    str))
     261            8 :     return TALER_MERCHANT_CONTRACT_TOKEN_KIND_SUBSCRIPTION;
     262            3 :   if (0 == strcmp ("discount",
     263              :                    str))
     264            3 :     return TALER_MERCHANT_CONTRACT_TOKEN_KIND_DISCOUNT;
     265            0 :   return TALER_MERCHANT_CONTRACT_TOKEN_KIND_INVALID;
     266              : }
        

Generated by: LCOV version 2.0-1