LCOV - code coverage report
Current view: top level - backend - taler-merchant-httpd_get-tips-ID.c (source / functions) Hit Total Coverage
Test: GNU Taler merchant coverage report Lines: 51 93 54.8 %
Date: 2021-08-30 06:54:17 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   (C) 2014-2021 Taler Systems SA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU Affero 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 taler-merchant-httpd_get-tips-ID.c
      18             :  * @brief implementation of GET /tips/$ID
      19             :  * @author Marcello Stanisci
      20             :  * @author Christian Grothoff
      21             :  */
      22             : #include "platform.h"
      23             : #include <jansson.h>
      24             : #include <taler/taler_signatures.h>
      25             : #include <taler/taler_json_lib.h>
      26             : #include "taler-merchant-httpd_get-tips-ID.h"
      27             : #include "taler-merchant-httpd_mhd.h"
      28             : #include "taler-merchant-httpd_qr.h"
      29             : #include "taler-merchant-httpd_templating.h"
      30             : 
      31             : char *
      32           2 : TMH_make_taler_tip_uri (struct MHD_Connection *con,
      33             :                         const struct GNUNET_HashCode *tip_id,
      34             :                         const char *instance_id)
      35             : {
      36             :   const char *host;
      37             :   const char *forwarded_host;
      38             :   const char *uri_path;
      39           2 :   struct GNUNET_Buffer buf = { 0 };
      40             : 
      41           2 :   host = MHD_lookup_connection_value (con,
      42             :                                       MHD_HEADER_KIND,
      43             :                                       "Host");
      44           2 :   forwarded_host = MHD_lookup_connection_value (con,
      45             :                                                 MHD_HEADER_KIND,
      46             :                                                 "X-Forwarded-Host");
      47             : 
      48           2 :   uri_path = MHD_lookup_connection_value (con,
      49             :                                           MHD_HEADER_KIND,
      50             :                                           "X-Forwarded-Prefix");
      51           2 :   if (NULL != forwarded_host)
      52           0 :     host = forwarded_host;
      53             : 
      54           2 :   if (NULL == host)
      55             :   {
      56           0 :     GNUNET_break (0);
      57           0 :     return NULL;
      58             :   }
      59             : 
      60           2 :   GNUNET_assert (NULL != instance_id);
      61           2 :   GNUNET_assert (NULL != tip_id);
      62             : 
      63           2 :   GNUNET_buffer_write_str (&buf,
      64             :                            "taler");
      65           2 :   if (GNUNET_NO == TALER_mhd_is_https (con))
      66           2 :     GNUNET_buffer_write_str (&buf,
      67             :                              "+http");
      68           2 :   GNUNET_buffer_write_str (&buf,
      69             :                            "://tip/");
      70           2 :   GNUNET_buffer_write_str (&buf,
      71             :                            host);
      72           2 :   if (NULL != uri_path)
      73           0 :     GNUNET_buffer_write_path (&buf,
      74             :                               uri_path);
      75           2 :   if (0 != strcmp ("default",
      76             :                    instance_id))
      77             :   {
      78           0 :     GNUNET_buffer_write_path (&buf,
      79             :                               "instances");
      80           0 :     GNUNET_buffer_write_path (&buf,
      81             :                               instance_id);
      82             :   }
      83             :   /* Ensure previous part is slash-terminated */
      84           2 :   GNUNET_buffer_write_path (&buf,
      85             :                             "");
      86           2 :   GNUNET_buffer_write_data_encoded (&buf,
      87             :                                     tip_id,
      88             :                                     sizeof (*tip_id));
      89           2 :   return GNUNET_buffer_reap_str (&buf);
      90             : }
      91             : 
      92             : 
      93             : char *
      94           2 : TMH_make_tip_status_url (struct MHD_Connection *con,
      95             :                          const struct GNUNET_HashCode *tip_id,
      96             :                          const char *instance_id)
      97             : {
      98             :   const char *host;
      99             :   const char *forwarded_host;
     100             :   const char *uri_path;
     101           2 :   struct GNUNET_Buffer buf = { 0 };
     102             : 
     103           2 :   host = MHD_lookup_connection_value (con,
     104             :                                       MHD_HEADER_KIND,
     105             :                                       "Host");
     106           2 :   forwarded_host = MHD_lookup_connection_value (con,
     107             :                                                 MHD_HEADER_KIND,
     108             :                                                 "X-Forwarded-Host");
     109             : 
     110           2 :   uri_path = MHD_lookup_connection_value (con,
     111             :                                           MHD_HEADER_KIND,
     112             :                                           "X-Forwarded-Prefix");
     113           2 :   if (NULL != forwarded_host)
     114           0 :     host = forwarded_host;
     115             : 
     116           2 :   if (NULL == host)
     117             :   {
     118           0 :     GNUNET_break (0);
     119           0 :     return NULL;
     120             :   }
     121             : 
     122           2 :   GNUNET_assert (NULL != instance_id);
     123           2 :   GNUNET_assert (NULL != tip_id);
     124             : 
     125           2 :   if (GNUNET_NO == TALER_mhd_is_https (con))
     126           2 :     GNUNET_buffer_write_str (&buf,
     127             :                              "http://");
     128             :   else
     129           0 :     GNUNET_buffer_write_str (&buf,
     130             :                              "https://");
     131           2 :   GNUNET_buffer_write_str (&buf,
     132             :                            host);
     133           2 :   if (NULL != uri_path)
     134           0 :     GNUNET_buffer_write_path (&buf,
     135             :                               uri_path);
     136           2 :   if (0 != strcmp ("default",
     137             :                    instance_id))
     138             :   {
     139           0 :     GNUNET_buffer_write_path (&buf,
     140             :                               "instances");
     141           0 :     GNUNET_buffer_write_path (&buf,
     142             :                               instance_id);
     143             :   }
     144           2 :   GNUNET_buffer_write_path (&buf,
     145             :                             "tips/");
     146           2 :   GNUNET_buffer_write_data_encoded (&buf,
     147             :                                     tip_id,
     148             :                                     sizeof (*tip_id));
     149           2 :   return GNUNET_buffer_reap_str (&buf);
     150             : }
     151             : 
     152             : 
     153             : MHD_RESULT
     154           2 : TMH_get_tips_ID (const struct TMH_RequestHandler *rh,
     155             :                  struct MHD_Connection *connection,
     156             :                  struct TMH_HandlerContext *hc)
     157             : {
     158             :   struct GNUNET_HashCode tip_id;
     159             :   enum GNUNET_DB_QueryStatus qs;
     160             :   struct TALER_Amount total_authorized;
     161             :   struct TALER_Amount total_picked_up;
     162             :   struct GNUNET_TIME_Absolute expiration;
     163             :   char *exchange_url;
     164             :   struct TALER_ReservePrivateKeyP reserve_priv;
     165             : 
     166           2 :   if (GNUNET_OK !=
     167           2 :       GNUNET_CRYPTO_hash_from_string (hc->infix,
     168             :                                       &tip_id))
     169             :   {
     170             :     /* tip_id has wrong encoding */
     171           0 :     GNUNET_break_op (0);
     172           0 :     return TALER_MHD_reply_with_error (connection,
     173             :                                        MHD_HTTP_BAD_REQUEST,
     174             :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     175           0 :                                        hc->infix);
     176             :   }
     177             : 
     178           2 :   TMH_db->preflight (TMH_db->cls);
     179           2 :   qs = TMH_db->lookup_tip (TMH_db->cls,
     180           2 :                            hc->instance->settings.id,
     181             :                            &tip_id,
     182             :                            &total_authorized,
     183             :                            &total_picked_up,
     184             :                            &expiration,
     185             :                            &exchange_url,
     186             :                            &reserve_priv);
     187           2 :   if (0 > qs)
     188             :   {
     189             :     /* single, read-only SQL statements should never cause
     190             :        serialization problems */
     191           0 :     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
     192             :     /* Always report on hard error as well to enable diagnostics */
     193           0 :     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
     194           0 :     return TALER_MHD_reply_with_error (connection,
     195             :                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
     196             :                                        TALER_EC_GENERIC_DB_FETCH_FAILED,
     197             :                                        NULL);
     198             :   }
     199           2 :   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     200             :   {
     201           0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     202             :                 "Unknown tip id given: `%s'\n",
     203             :                 hc->infix);
     204           0 :     return TALER_MHD_reply_with_error (connection,
     205             :                                        MHD_HTTP_NOT_FOUND,
     206             :                                        TALER_EC_MERCHANT_GENERIC_TIP_ID_UNKNOWN,
     207           0 :                                        hc->infix);
     208             :   }
     209             : 
     210             :   /* Build response */
     211             :   {
     212             :     struct TALER_Amount remaining;
     213           2 :     struct GNUNET_TIME_Absolute expiration_round = expiration;
     214             :     MHD_RESULT ret;
     215             : 
     216           2 :     GNUNET_break (0 <=
     217             :                   TALER_amount_subtract (&remaining,
     218             :                                          &total_authorized,
     219             :                                          &total_picked_up));
     220             : 
     221           2 :     GNUNET_TIME_round_abs (&expiration_round);
     222           2 :     if (TMH_MHD_test_html_desired (connection))
     223             :     {
     224             :       char *qr;
     225             :       char *uri;
     226             :       char *tip_status_url;
     227             : 
     228           0 :       uri = TMH_make_taler_tip_uri (connection,
     229             :                                     &tip_id,
     230           0 :                                     hc->instance->settings.id);
     231           0 :       tip_status_url = TMH_make_tip_status_url (connection,
     232             :                                                 &tip_id,
     233           0 :                                                 hc->instance->settings.id);
     234           0 :       qr = TMH_create_qrcode (uri);
     235           0 :       if (NULL == qr)
     236             :       {
     237           0 :         GNUNET_break (0);
     238           0 :         GNUNET_free (uri);
     239           0 :         ret = TALER_MHD_reply_with_error (connection,
     240             :                                           MHD_HTTP_INTERNAL_SERVER_ERROR,
     241             :                                           TALER_EC_GENERIC_ALLOCATION_FAILURE,
     242             :                                           "during QR code generation");
     243             :       }
     244             :       else
     245             :       {
     246             :         json_t *context;
     247             : 
     248           0 :         context = GNUNET_JSON_PACK (
     249             :           TALER_JSON_pack_amount ("remaining_tip",
     250             :                                   &remaining),
     251             :           GNUNET_JSON_pack_string ("taler_tip_uri",
     252             :                                    uri),
     253             :           GNUNET_JSON_pack_string ("taler_tip_qrcode_svg",
     254             :                                    qr));
     255           0 :         ret = TMH_return_from_template (connection,
     256           0 :                                         ( (0 == remaining.value) &&
     257           0 :                                           (0 == remaining.fraction) )
     258             :                                         ? MHD_HTTP_GONE
     259             :                                         : MHD_HTTP_OK,
     260           0 :                                         ( (0 == remaining.value) &&
     261           0 :                                           (0 == remaining.fraction) )
     262             :                                         ? "depleted_tip"
     263             :                                         : "offer_tip",
     264           0 :                                         hc->instance->settings.id,
     265             :                                         uri,
     266             :                                         context);
     267           0 :         json_decref (context);
     268             :       }
     269           0 :       GNUNET_free (tip_status_url);
     270           0 :       GNUNET_free (uri);
     271           0 :       GNUNET_free (qr);
     272             :     }
     273             :     else
     274             :     {
     275           2 :       ret = TALER_MHD_REPLY_JSON_PACK (
     276             :         connection,
     277             :         ( (0 == remaining.value) &&
     278             :           (0 == remaining.fraction) )
     279             :         ? MHD_HTTP_GONE
     280             :         : MHD_HTTP_OK,
     281             :         GNUNET_JSON_pack_string ("exchange_url",
     282             :                                  exchange_url),
     283             :         TALER_JSON_pack_amount ("tip_amount",
     284             :                                 &remaining),
     285             :         GNUNET_JSON_pack_time_abs ("expiration",
     286             :                                    expiration_round));
     287             :     }
     288           2 :     GNUNET_free (exchange_url);
     289           2 :     return ret;
     290             :   }
     291             : }
     292             : 
     293             : 
     294             : /* end of taler-merchant-httpd_get-tips-ID.c */

Generated by: LCOV version 1.14