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 */