Line data Source code
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 0 : handle_render_form_finished (void *cls,
44 : long response_code,
45 : const void *body,
46 : size_t body_size)
47 : {
48 0 : struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh = cls;
49 0 : json_t *json = NULL;
50 0 : struct TALER_EXCHANGE_PostAmlRenderFormResponse response = {
51 0 : .hr.http_status = (unsigned int) response_code
52 : };
53 :
54 0 : parfh->job = NULL;
55 0 : if (MHD_HTTP_OK == response_code)
56 : {
57 0 : response.details.ok.pdf = body;
58 0 : response.details.ok.pdf_size = body_size;
59 : }
60 : else
61 : {
62 : json_error_t error;
63 :
64 0 : if ( (NULL != body) &&
65 : (0 != body_size) )
66 0 : json = json_loadb (body,
67 : body_size,
68 : JSON_REJECT_DUPLICATES,
69 : &error);
70 0 : response.hr.reply = json;
71 0 : if (0 == response_code)
72 : {
73 0 : response.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
74 0 : response.hr.hint = "server offline?";
75 : }
76 : else
77 : {
78 0 : response.hr.ec = TALER_JSON_get_error_code (json);
79 0 : response.hr.hint = TALER_JSON_get_error_hint (json);
80 : }
81 : }
82 0 : if (NULL != parfh->cb)
83 : {
84 0 : parfh->cb (parfh->cb_cls,
85 : &response);
86 0 : parfh->cb = NULL;
87 : }
88 0 : if (NULL != json)
89 0 : json_decref (json);
90 0 : TALER_EXCHANGE_post_aml_render_form_cancel (parfh);
91 0 : }
92 :
93 :
94 : struct TALER_EXCHANGE_PostAmlRenderFormHandle *
95 0 : 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 0 : if ( (NULL == ctx) ||
104 0 : (NULL == url) ||
105 0 : (NULL == officer_priv) ||
106 0 : (! json_is_object (form)) ||
107 0 : (! json_is_string (json_object_get (form,
108 : "FORM_ID"))) )
109 : {
110 0 : GNUNET_break (0);
111 0 : return NULL;
112 : }
113 0 : parfh = GNUNET_new (struct TALER_EXCHANGE_PostAmlRenderFormHandle);
114 0 : parfh->ctx = ctx;
115 0 : parfh->base_url = GNUNET_strdup (url);
116 0 : parfh->officer_priv = *officer_priv;
117 0 : GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
118 : &parfh->officer_pub.eddsa_pub);
119 0 : parfh->form = json_deep_copy (form);
120 0 : if (NULL == parfh->form)
121 : {
122 0 : TALER_EXCHANGE_post_aml_render_form_cancel (parfh);
123 0 : return NULL;
124 : }
125 0 : return parfh;
126 : }
127 :
128 :
129 : enum TALER_ErrorCode
130 0 : 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 0 : if (NULL != parfh->job)
145 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
146 0 : parfh->cb = cb;
147 0 : parfh->cb_cls = cb_cls;
148 0 : TALER_officer_aml_query_sign (&parfh->officer_priv,
149 : &officer_sig);
150 0 : end = GNUNET_STRINGS_data_to_string (&parfh->officer_pub,
151 : sizeof (parfh->officer_pub),
152 : pub_str,
153 : sizeof (pub_str));
154 0 : *end = '\0';
155 0 : GNUNET_asprintf (&path,
156 : "aml/%s/render-form",
157 : pub_str);
158 0 : parfh->url = TALER_url_join (parfh->base_url,
159 : path,
160 : NULL);
161 0 : GNUNET_free (path);
162 0 : if (NULL == parfh->url)
163 0 : return TALER_EC_GENERIC_CONFIGURATION_INVALID;
164 0 : eh = TALER_EXCHANGE_curl_easy_get_ (parfh->url);
165 0 : if ( (NULL == eh) ||
166 : (GNUNET_OK !=
167 0 : TALER_curl_easy_post (&parfh->post_ctx,
168 : eh,
169 0 : parfh->form)) )
170 : {
171 0 : if (NULL != eh)
172 0 : curl_easy_cleanup (eh);
173 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
174 : }
175 0 : end = GNUNET_STRINGS_data_to_string (&officer_sig,
176 : sizeof (officer_sig),
177 : sig_str,
178 : sizeof (sig_str));
179 0 : *end = '\0';
180 0 : GNUNET_asprintf (&header,
181 : "%s: %s",
182 : TALER_AML_OFFICER_SIGNATURE_HEADER,
183 : sig_str);
184 0 : headers = curl_slist_append (parfh->post_ctx.headers,
185 : header);
186 0 : GNUNET_free (header);
187 0 : if (NULL == headers)
188 : {
189 0 : curl_easy_cleanup (eh);
190 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
191 : }
192 0 : parfh->post_ctx.headers = headers;
193 0 : parfh->job = GNUNET_CURL_job_add_raw (parfh->ctx,
194 : eh,
195 0 : parfh->post_ctx.headers,
196 : &handle_render_form_finished,
197 : parfh);
198 0 : if (NULL == parfh->job)
199 : {
200 0 : curl_easy_cleanup (eh);
201 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
202 : }
203 0 : return TALER_EC_NONE;
204 : }
205 :
206 :
207 : void
208 0 : TALER_EXCHANGE_post_aml_render_form_cancel (
209 : struct TALER_EXCHANGE_PostAmlRenderFormHandle *parfh)
210 : {
211 0 : if (NULL == parfh)
212 0 : return;
213 0 : if (NULL != parfh->job)
214 : {
215 0 : GNUNET_CURL_job_cancel (parfh->job);
216 0 : parfh->job = NULL;
217 : }
218 0 : TALER_curl_easy_post_finished (&parfh->post_ctx);
219 0 : if (NULL != parfh->form)
220 0 : json_decref (parfh->form);
221 0 : GNUNET_free (parfh->url);
222 0 : GNUNET_free (parfh->base_url);
223 0 : GNUNET_free (parfh);
224 : }
225 :
226 :
227 : /* end of exchange_api_post-aml-OFFICER_PUB-render-form.c */
|