LCOV - code coverage report
Current view: top level - lib - merchant_api_common.c (source / functions) Hit Total Coverage
Test: GNU Taler coverage report Lines: 113 175 64.6 %
Date: 2021-04-12 06:04:58 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2020 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 2.1, 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 Lesser General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU Lesser General Public License along with
      14             :   TALER; see the file COPYING.LGPL.  If not, see
      15             :   <http://www.gnu.org/licenses/>
      16             : */
      17             : /**
      18             :  * @file merchant_api_common.c
      19             :  * @brief Implementation of common logic for libtalermerchant
      20             :  * @author Christian Grothoff
      21             :  */
      22             : #include "platform.h"
      23             : #include <curl/curl.h>
      24             : #include <jansson.h>
      25             : #include <microhttpd.h> /* just for HTTP status codes */
      26             : #include <gnunet/gnunet_util_lib.h>
      27             : #include <gnunet/gnunet_uri_lib.h>
      28             : #include <gnunet/gnunet_curl_lib.h>
      29             : #include "taler_merchant_service.h"
      30             : #include <taler/taler_json_lib.h>
      31             : 
      32             : 
      33             : void
      34           0 : TALER_MERCHANT_parse_error_details_ (const json_t *response,
      35             :                                      unsigned int http_status,
      36             :                                      struct TALER_MERCHANT_HttpResponse *hr)
      37             : {
      38             :   const json_t *jc;
      39             : 
      40           0 :   memset (hr, 0, sizeof (*hr));
      41           0 :   hr->reply = response;
      42           0 :   hr->http_status = http_status;
      43           0 :   if (NULL == response)
      44             :   {
      45           0 :     hr->ec = TALER_EC_GENERIC_INVALID_RESPONSE;
      46           0 :     return;
      47             :   }
      48           0 :   hr->ec = TALER_JSON_get_error_code (response);
      49           0 :   hr->hint = TALER_JSON_get_error_hint (response);
      50             : 
      51             :   /* handle 'exchange_http_status' */
      52           0 :   jc = json_object_get (response,
      53             :                         "exchange_http_status");
      54             :   /* The caller already knows that the JSON represents an error,
      55             :      so we are dealing with a missing error code here.  */
      56           0 :   if (NULL == jc)
      57           0 :     return; /* no need to bother with exchange_code/hint if we had no status */
      58           0 :   if (! json_is_integer (jc))
      59             :   {
      60           0 :     GNUNET_break_op (0);
      61           0 :     return;
      62             :   }
      63           0 :   hr->exchange_http_status = (unsigned int) json_integer_value (jc);
      64             : 
      65             :   /* handle 'exchange_reply' */
      66           0 :   jc = json_object_get (response,
      67             :                         "exchange_reply");
      68           0 :   if (! json_is_object (jc))
      69             :   {
      70           0 :     GNUNET_break_op (0);
      71             :   }
      72             :   else
      73             :   {
      74           0 :     hr->exchange_reply = jc;
      75             :   }
      76             : 
      77             :   /* handle 'exchange_code' */
      78           0 :   jc = json_object_get (response,
      79             :                         "exchange_code");
      80             :   /* The caller already knows that the JSON represents an error,
      81             :      so we are dealing with a missing error code here.  */
      82           0 :   if (NULL == jc)
      83           0 :     return; /* no need to bother with exchange-hint if we had no code */
      84           0 :   if (! json_is_integer (jc))
      85             :   {
      86           0 :     GNUNET_break_op (0);
      87           0 :     hr->exchange_code = TALER_EC_INVALID;
      88             :   }
      89             :   else
      90             :   {
      91           0 :     hr->exchange_code = (enum TALER_ErrorCode) json_integer_value (jc);
      92             :   }
      93             : 
      94             :   /* handle 'exchange-hint' */
      95           0 :   jc = json_object_get (response,
      96             :                         "exchange-hint");
      97             :   /* The caller already knows that the JSON represents an error,
      98             :      so we are dealing with a missing error code here.  */
      99           0 :   if (NULL == jc)
     100           0 :     return;
     101           0 :   if (! json_is_string (jc))
     102             :   {
     103           0 :     GNUNET_break_op (0);
     104             :   }
     105             :   else
     106             :   {
     107           0 :     hr->exchange_hint = json_string_value (jc);
     108             :   }
     109             : }
     110             : 
     111             : 
     112             : char *
     113           0 : TALER_MERCHANT_baseurl_add_instance (const char *base_url,
     114             :                                      const char *instance_id)
     115             : {
     116             :   char *ret;
     117             :   bool end_sl;
     118             : 
     119           0 :   if ('\0' == *base_url)
     120             :   {
     121           0 :     GNUNET_break (0);
     122           0 :     return NULL;
     123             :   }
     124           0 :   end_sl = '/' == base_url[strlen (base_url) - 1];
     125             : 
     126           0 :   GNUNET_asprintf (&ret,
     127             :                    (end_sl)
     128             :                    ? "%sinstances/%s/"
     129             :                    : "%s/instances/%s/",
     130             :                    base_url,
     131             :                    instance_id);
     132           0 :   return ret;
     133             : }
     134             : 
     135             : 
     136             : int
     137           7 : TALER_MERCHANT_parse_pay_uri (const char *pay_uri,
     138             :                               struct TALER_MERCHANT_PayUriData *parse_data)
     139             : {
     140           7 :   char *cp = GNUNET_strdup (pay_uri);
     141             :   struct GNUNET_Uri u;
     142             : 
     143           7 :   if (0 !=
     144           7 :       GNUNET_uri_parse (&u,
     145             :                         cp))
     146             :   {
     147           0 :     GNUNET_free (cp);
     148           0 :     GNUNET_break_op (0);
     149           0 :     return GNUNET_SYSERR;
     150             :   }
     151           7 :   if ((0 != strcasecmp ("taler",
     152           7 :                         u.scheme)) &&
     153           3 :       (0 != strcasecmp ("taler+http",
     154           3 :                         u.scheme)))
     155             :   {
     156           1 :     fprintf (stderr,
     157             :              "Bad schema %s\n",
     158             :              u.scheme);
     159           1 :     GNUNET_free (cp);
     160           1 :     GNUNET_break_op (0);
     161           1 :     return GNUNET_SYSERR;
     162             :   }
     163           6 :   parse_data->use_http = (0 == strcasecmp ("taler+http",
     164           6 :                                            u.scheme));
     165           6 :   if (0 != strcasecmp ("pay",
     166           6 :                        u.host))
     167             :   {
     168           1 :     GNUNET_break_op (0);
     169           1 :     GNUNET_free (cp);
     170           1 :     return GNUNET_SYSERR;
     171             :   }
     172             : 
     173             :   {
     174             :     char *order_id;
     175             :     char *mpp;
     176           5 :     char *session_id = strrchr (u.path,
     177             :                                 '/');
     178           5 :     struct TALER_ClaimTokenP *claim_token = NULL;
     179             : 
     180           5 :     if (NULL == session_id)
     181             :     {
     182           0 :       GNUNET_break_op (0);
     183           0 :       GNUNET_free (cp);
     184           0 :       return GNUNET_SYSERR;
     185             :     }
     186           5 :     *session_id = '\0';
     187           5 :     ++session_id;
     188             : 
     189           5 :     order_id = strrchr (u.path,
     190             :                         '/');
     191           5 :     if (NULL == order_id)
     192             :     {
     193           1 :       GNUNET_break_op (0);
     194           1 :       GNUNET_free (cp);
     195           1 :       return GNUNET_SYSERR;
     196             :     }
     197           4 :     *order_id = '\0';
     198           4 :     ++order_id;
     199           4 :     mpp = strchr (u.path,
     200             :                   '/');
     201           4 :     if (NULL != mpp)
     202             :     {
     203           1 :       *mpp = '\0';
     204           1 :       ++mpp;
     205             :     }
     206             : 
     207             :     {
     208           4 :       char *ct_str = u.query;
     209             :       char *ct_data;
     210             : 
     211           4 :       if (NULL != ct_str)
     212             :       {
     213           1 :         ct_data = strchr (u.query,
     214             :                           '=');
     215           1 :         if (NULL == ct_data)
     216             :         {
     217           0 :           GNUNET_break_op (0);
     218           0 :           GNUNET_free (cp);
     219           0 :           return GNUNET_SYSERR;
     220             :         }
     221           1 :         *ct_data = '\0';
     222           1 :         ++ct_data;
     223           1 :         claim_token = GNUNET_new (struct TALER_ClaimTokenP);
     224           1 :         if ( (0 != strcmp ("c",
     225           2 :                            u.query)) ||
     226             :              (GNUNET_OK !=
     227           1 :               GNUNET_STRINGS_string_to_data (ct_data,
     228             :                                              strlen (ct_data),
     229             :                                              claim_token,
     230             :                                              sizeof (*claim_token))) )
     231             :         {
     232           0 :           GNUNET_break_op (0);
     233           0 :           GNUNET_free (claim_token);
     234           0 :           GNUNET_free (cp);
     235           0 :           return GNUNET_SYSERR;
     236             :         }
     237             :       }
     238             :     }
     239             : 
     240             :     parse_data->merchant_prefix_path
     241           4 :       = (NULL == mpp)
     242             :         ? NULL
     243           4 :         : GNUNET_strdup (mpp);
     244           4 :     parse_data->merchant_host = GNUNET_strdup (u.path);
     245           4 :     parse_data->order_id = GNUNET_strdup (order_id);
     246             :     parse_data->session_id
     247           8 :       = (0 < strlen (session_id))
     248           2 :         ? GNUNET_strdup (session_id)
     249           4 :         : NULL;
     250           4 :     parse_data->claim_token = claim_token;
     251             :     parse_data->ssid
     252           8 :       = (NULL == u.fragment)
     253             :         ? NULL
     254           4 :         : GNUNET_strdup (u.fragment);
     255             :   }
     256           4 :   GNUNET_free (cp);
     257           4 :   return GNUNET_OK;
     258             : }
     259             : 
     260             : 
     261             : void
     262           4 : TALER_MERCHANT_parse_pay_uri_free (
     263             :   struct TALER_MERCHANT_PayUriData *parse_data)
     264             : {
     265           4 :   GNUNET_free (parse_data->merchant_host);
     266           4 :   GNUNET_free (parse_data->merchant_prefix_path);
     267           4 :   GNUNET_free (parse_data->order_id);
     268           4 :   GNUNET_free (parse_data->session_id);
     269           4 :   GNUNET_free (parse_data->claim_token);
     270           4 :   GNUNET_free (parse_data->ssid);
     271           4 : }
     272             : 
     273             : 
     274             : int
     275           5 : TALER_MERCHANT_parse_refund_uri (
     276             :   const char *refund_uri,
     277             :   struct TALER_MERCHANT_RefundUriData *parse_data)
     278             : {
     279           5 :   char *cp = GNUNET_strdup (refund_uri);
     280             :   struct GNUNET_Uri u;
     281             : 
     282           5 :   if (0 !=
     283           5 :       GNUNET_uri_parse (&u,
     284             :                         cp))
     285             :   {
     286           0 :     GNUNET_free (cp);
     287           0 :     GNUNET_break_op (0);
     288           0 :     return GNUNET_SYSERR;
     289             :   }
     290           5 :   if ((0 != strcasecmp ("taler",
     291           5 :                         u.scheme)) &&
     292           2 :       (0 != strcasecmp ("taler+http",
     293           2 :                         u.scheme)))
     294             :   {
     295           1 :     GNUNET_free (cp);
     296           1 :     GNUNET_break_op (0);
     297           1 :     return GNUNET_SYSERR;
     298             :   }
     299           4 :   parse_data->use_http = (0 == strcasecmp ("taler+http",
     300           4 :                                            u.scheme));
     301             : 
     302           4 :   if (0 != strcasecmp ("refund",
     303           4 :                        u.host))
     304             :   {
     305           1 :     GNUNET_break_op (0);
     306           1 :     GNUNET_free (cp);
     307           1 :     return GNUNET_SYSERR;
     308             :   }
     309             : 
     310             :   {
     311             :     char *order_id;
     312           3 :     char *last_seg = strrchr (u.path,
     313             :                               '/');
     314             : 
     315           3 :     if (NULL == last_seg)
     316             :     {
     317           0 :       GNUNET_break_op (0);
     318           0 :       GNUNET_free (cp);
     319           0 :       return GNUNET_SYSERR;
     320             :     }
     321           3 :     *last_seg = '\0';
     322           3 :     ++last_seg;
     323             : 
     324           3 :     order_id = strrchr (u.path,
     325             :                         '/');
     326           3 :     if (NULL == order_id)
     327             :     {
     328           1 :       GNUNET_break_op (0);
     329           1 :       GNUNET_free (cp);
     330           1 :       return GNUNET_SYSERR;
     331             :     }
     332           2 :     *order_id = '\0';
     333           2 :     ++order_id;
     334           2 :     if (0 != strlen (last_seg))
     335             :     {
     336           0 :       GNUNET_break_op (0);
     337           0 :       GNUNET_free (cp);
     338           0 :       return GNUNET_SYSERR;
     339             :     }
     340             : 
     341             :     {
     342             :       char *mpp;
     343             : 
     344           2 :       mpp = strchr (u.path,
     345             :                     '/');
     346           2 :       if (NULL != mpp)
     347             :       {
     348           1 :         *mpp = '\0';
     349           1 :         ++mpp;
     350             :       }
     351             : 
     352             :       parse_data->merchant_prefix_path
     353           2 :         = (NULL == mpp)
     354             :           ? NULL
     355           2 :           : GNUNET_strdup (mpp);
     356             :     }
     357           2 :     parse_data->merchant_host = GNUNET_strdup (u.path);
     358           2 :     parse_data->order_id = GNUNET_strdup (order_id);
     359             :     parse_data->ssid
     360           4 :       = (NULL == u.fragment)
     361             :         ? NULL
     362           2 :         : GNUNET_strdup (u.fragment);
     363             :   }
     364           2 :   GNUNET_free (cp);
     365           2 :   return GNUNET_OK;
     366             : }
     367             : 
     368             : 
     369             : void
     370           2 : TALER_MERCHANT_parse_refund_uri_free (
     371             :   struct TALER_MERCHANT_RefundUriData *parse_data)
     372             : {
     373           2 :   GNUNET_free (parse_data->merchant_host);
     374           2 :   GNUNET_free (parse_data->merchant_prefix_path);
     375           2 :   GNUNET_free (parse_data->order_id);
     376           2 :   GNUNET_free (parse_data->ssid);
     377           2 : }

Generated by: LCOV version 1.14