exchange

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

exchange_api_post-aml-OFFICER_PUB-render-form.c (6715B)


      1 /*
      2   This file is part of TALER
      3   Copyright (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 General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 */
      9 /**
     10  * @file lib/exchange_api_post-aml-OFFICER_PUB-render-form.c
     11  * @brief Implementation of POST /aml/$OFFICER_PUB/render-form
     12  */
     13 #include "platform.h"
     14 #include <curl/curl.h>
     15 #include <jansson.h>
     16 #include <microhttpd.h> /* just for HTTP status codes */
     17 #include "taler/taler_curl_lib.h"
     18 #include "taler/taler_json_lib.h"
     19 #include "taler/taler_util.h"
     20 #include "taler/exchange/post-aml-OFFICER_PUB-render-form.h"
     21 #include "exchange_api_curl_defaults.h"
     22 
     23 
     24 struct TALER_EXCHANGE_PostAmlRenderFormHandle
     25 {
     26   struct GNUNET_CURL_Context *ctx;
     27   struct GNUNET_CURL_Job *job;
     28   struct TALER_CURL_PostContext post_ctx;
     29   char *base_url;
     30   char *url;
     31   struct TALER_AmlOfficerPrivateKeyP officer_priv;
     32   struct TALER_AmlOfficerPublicKeyP officer_pub;
     33   json_t *form;
     34   TALER_EXCHANGE_PostAmlRenderFormCallback cb;
     35   TALER_EXCHANGE_POST_AML_RENDER_FORM_RESULT_CLOSURE *cb_cls;
     36 };
     37 
     38 
     39 /**
     40  * Complete a raw PDF request.
     41  */
     42 static void
     43 handle_render_form_finished (void *cls,
     44                              long response_code,
     45                              const void *body,
     46                              size_t body_size)
     47 {
     48   struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh = cls;
     49   json_t *json = NULL;
     50   struct TALER_EXCHANGE_PostAmlRenderFormResponse response = {
     51     .hr.http_status = (unsigned int) response_code
     52   };
     53 
     54   parfh->job = NULL;
     55   if (MHD_HTTP_OK == response_code)
     56   {
     57     response.details.ok.pdf = body;
     58     response.details.ok.pdf_size = body_size;
     59   }
     60   else
     61   {
     62     json_error_t error;
     63 
     64     if ( (NULL != body) &&
     65          (0 != body_size) )
     66       json = json_loadb (body,
     67                          body_size,
     68                          JSON_REJECT_DUPLICATES,
     69                          &error);
     70     response.hr.reply = json;
     71     if (0 == response_code)
     72     {
     73       response.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     74       response.hr.hint = "server offline?";
     75     }
     76     else
     77     {
     78       response.hr.ec = TALER_JSON_get_error_code (json);
     79       response.hr.hint = TALER_JSON_get_error_hint (json);
     80     }
     81   }
     82   if (NULL != parfh->cb)
     83   {
     84     parfh->cb (parfh->cb_cls,
     85                &response);
     86     parfh->cb = NULL;
     87   }
     88   if (NULL != json)
     89     json_decref (json);
     90   TALER_EXCHANGE_post_aml_render_form_cancel (parfh);
     91 }
     92 
     93 
     94 struct TALER_EXCHANGE_PostAmlRenderFormHandle *
     95 TALER_EXCHANGE_post_aml_render_form_create (
     96   struct GNUNET_CURL_Context *ctx,
     97   const char *url,
     98   const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
     99   const json_t *form)
    100 {
    101   struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh;
    102 
    103   if ( (NULL == ctx) ||
    104        (NULL == url) ||
    105        (NULL == officer_priv) ||
    106        (! json_is_object (form)) ||
    107        (! json_is_string (json_object_get (form,
    108                                            "FORM_ID"))) )
    109   {
    110     GNUNET_break (0);
    111     return NULL;
    112   }
    113   parfh = GNUNET_new (struct TALER_EXCHANGE_PostAmlRenderFormHandle);
    114   parfh->ctx = ctx;
    115   parfh->base_url = GNUNET_strdup (url);
    116   parfh->officer_priv = *officer_priv;
    117   GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
    118                                      &parfh->officer_pub.eddsa_pub);
    119   parfh->form = json_deep_copy (form);
    120   if (NULL == parfh->form)
    121   {
    122     TALER_EXCHANGE_post_aml_render_form_cancel (parfh);
    123     return NULL;
    124   }
    125   return parfh;
    126 }
    127 
    128 
    129 enum TALER_ErrorCode
    130 TALER_EXCHANGE_post_aml_render_form_start (
    131   struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh,
    132   TALER_EXCHANGE_PostAmlRenderFormCallback cb,
    133   TALER_EXCHANGE_POST_AML_RENDER_FORM_RESULT_CLOSURE *cb_cls)
    134 {
    135   struct TALER_AmlOfficerSignatureP officer_sig;
    136   char pub_str[sizeof (parfh->officer_pub) * 2];
    137   char sig_str[sizeof (officer_sig) * 2];
    138   char *path;
    139   char *header;
    140   char *end;
    141   CURL *eh;
    142   struct curl_slist *headers;
    143 
    144   if (NULL != parfh->job)
    145     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    146   parfh->cb = cb;
    147   parfh->cb_cls = cb_cls;
    148   TALER_officer_aml_query_sign (&parfh->officer_priv,
    149                                 &officer_sig);
    150   end = GNUNET_STRINGS_data_to_string (&parfh->officer_pub,
    151                                        sizeof (parfh->officer_pub),
    152                                        pub_str,
    153                                        sizeof (pub_str));
    154   *end = '\0';
    155   GNUNET_asprintf (&path,
    156                    "aml/%s/render-form",
    157                    pub_str);
    158   parfh->url = TALER_url_join (parfh->base_url,
    159                                path,
    160                                NULL);
    161   GNUNET_free (path);
    162   if (NULL == parfh->url)
    163     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    164   eh = TALER_EXCHANGE_curl_easy_get_ (parfh->url);
    165   if ( (NULL == eh) ||
    166        (GNUNET_OK !=
    167         TALER_curl_easy_post (&parfh->post_ctx,
    168                               eh,
    169                               parfh->form)) )
    170   {
    171     if (NULL != eh)
    172       curl_easy_cleanup (eh);
    173     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    174   }
    175   end = GNUNET_STRINGS_data_to_string (&officer_sig,
    176                                        sizeof (officer_sig),
    177                                        sig_str,
    178                                        sizeof (sig_str));
    179   *end = '\0';
    180   GNUNET_asprintf (&header,
    181                    "%s: %s",
    182                    TALER_AML_OFFICER_SIGNATURE_HEADER,
    183                    sig_str);
    184   headers = curl_slist_append (parfh->post_ctx.headers,
    185                                header);
    186   GNUNET_free (header);
    187   if (NULL == headers)
    188   {
    189     curl_easy_cleanup (eh);
    190     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    191   }
    192   parfh->post_ctx.headers = headers;
    193   parfh->job = GNUNET_CURL_job_add_raw (parfh->ctx,
    194                                         eh,
    195                                         parfh->post_ctx.headers,
    196                                         &handle_render_form_finished,
    197                                         parfh);
    198   if (NULL == parfh->job)
    199   {
    200     curl_easy_cleanup (eh);
    201     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    202   }
    203   return TALER_EC_NONE;
    204 }
    205 
    206 
    207 void
    208 TALER_EXCHANGE_post_aml_render_form_cancel (
    209   struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh)
    210 {
    211   if (NULL == parfh)
    212     return;
    213   if (NULL != parfh->job)
    214   {
    215     GNUNET_CURL_job_cancel (parfh->job);
    216     parfh->job = NULL;
    217   }
    218   TALER_curl_easy_post_finished (&parfh->post_ctx);
    219   if (NULL != parfh->form)
    220     json_decref (parfh->form);
    221   GNUNET_free (parfh->url);
    222   GNUNET_free (parfh->base_url);
    223   GNUNET_free (parfh);
    224 }
    225 
    226 
    227 /* end of exchange_api_post-aml-OFFICER_PUB-render-form.c */