LCOV - code coverage report
Current view: top level - lib - exchange_api_get_aml_measures.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 220 0
Test Date: 2025-12-28 14:06:02 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2023, 2024 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              :   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
      15              :   <http://www.gnu.org/licenses/>
      16              : */
      17              : /**
      18              :  * @file lib/exchange_api_get_aml_measures.c
      19              :  * @brief Implementation of the GET /aml/$OFFICER_PUB/measures request
      20              :  * @author Christian Grothoff
      21              :  */
      22              : #include "taler/platform.h"
      23              : #include <microhttpd.h> /* just for HTTP status codes */
      24              : #include <gnunet/gnunet_util_lib.h>
      25              : #include <gnunet/gnunet_curl_lib.h>
      26              : #include "taler/taler_exchange_service.h"
      27              : #include "taler/taler_json_lib.h"
      28              : #include "exchange_api_handle.h"
      29              : #include "taler/taler_signatures.h"
      30              : #include "exchange_api_curl_defaults.h"
      31              : 
      32              : 
      33              : /**
      34              :  * Scrap buffer of temporary arrays.
      35              :  */
      36              : struct Scrap
      37              : {
      38              :   /**
      39              :    * Kept in DLL.
      40              :    */
      41              :   struct Scrap *next;
      42              : 
      43              :   /**
      44              :    * Kept in DLL.
      45              :    */
      46              :   struct Scrap *prev;
      47              : 
      48              :   /**
      49              :    * Pointer to our allocation.
      50              :    */
      51              :   const char **ptr;
      52              : };
      53              : 
      54              : 
      55              : /**
      56              :  * @brief A GET /aml/$OFFICER_PUB/measures Handle
      57              :  */
      58              : struct TALER_EXCHANGE_AmlGetMeasuresHandle
      59              : {
      60              : 
      61              :   /**
      62              :    * The url for this request.
      63              :    */
      64              :   char *url;
      65              : 
      66              :   /**
      67              :    * Handle for the request.
      68              :    */
      69              :   struct GNUNET_CURL_Job *job;
      70              : 
      71              :   /**
      72              :    * Function to call with the result.
      73              :    */
      74              :   TALER_EXCHANGE_AmlMeasuresCallback measures_cb;
      75              : 
      76              :   /**
      77              :    * Closure for @e measures_cb.
      78              :    */
      79              :   void *measures_cb_cls;
      80              : 
      81              :   /**
      82              :    * HTTP headers for the job.
      83              :    */
      84              :   struct curl_slist *job_headers;
      85              : 
      86              :   /**
      87              :    * Head of scrap list.
      88              :    */
      89              :   struct Scrap *scrap_head;
      90              : 
      91              :   /**
      92              :    * Tail of scrap list.
      93              :    */
      94              :   struct Scrap *scrap_tail;
      95              : };
      96              : 
      97              : 
      98              : /**
      99              :  * Parse AML measures.
     100              :  *
     101              :  * @param jroots JSON object with measure data
     102              :  * @param[out] roots where to write the result
     103              :  * @return #GNUNET_OK on success
     104              :  */
     105              : static enum GNUNET_GenericReturnValue
     106            0 : parse_aml_roots (
     107              :   const json_t *jroots,
     108              :   struct TALER_EXCHANGE_AvailableAmlMeasures *roots)
     109              : {
     110              :   const json_t *obj;
     111              :   const char *name;
     112            0 :   size_t idx = 0;
     113              : 
     114            0 :   json_object_foreach ((json_t *) jroots, name, obj)
     115              :   {
     116            0 :     struct TALER_EXCHANGE_AvailableAmlMeasures *root
     117            0 :       = &roots[idx++];
     118              :     struct GNUNET_JSON_Specification spec[] = {
     119            0 :       GNUNET_JSON_spec_string ("check_name",
     120              :                                &root->check_name),
     121            0 :       GNUNET_JSON_spec_string ("prog_name",
     122              :                                &root->prog_name),
     123            0 :       GNUNET_JSON_spec_mark_optional (
     124              :         GNUNET_JSON_spec_object_const ("context",
     125              :                                        &root->context),
     126              :         NULL),
     127            0 :       GNUNET_JSON_spec_end ()
     128              :     };
     129              : 
     130            0 :     if (GNUNET_OK !=
     131            0 :         GNUNET_JSON_parse (obj,
     132              :                            spec,
     133              :                            NULL,
     134              :                            NULL))
     135              :     {
     136            0 :       GNUNET_break_op (0);
     137            0 :       return GNUNET_SYSERR;
     138              :     }
     139            0 :     root->measure_name = name;
     140              :   }
     141            0 :   return GNUNET_OK;
     142              : }
     143              : 
     144              : 
     145              : /**
     146              :  * Create array of length @a len in scrap book.
     147              :  *
     148              :  * @param[in,out] lh context for allocations
     149              :  * @param len length of array
     150              :  * @return scrap array
     151              :  */
     152              : static const char **
     153            0 : make_scrap (
     154              :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
     155              :   unsigned int len)
     156              : {
     157            0 :   struct Scrap *s = GNUNET_new (struct Scrap);
     158              : 
     159            0 :   s->ptr = GNUNET_new_array (len,
     160              :                              const char *);
     161            0 :   GNUNET_CONTAINER_DLL_insert (lh->scrap_head,
     162              :                                lh->scrap_tail,
     163              :                                s);
     164            0 :   return s->ptr;
     165              : }
     166              : 
     167              : 
     168              : /**
     169              :  * Free all scrap space.
     170              :  *
     171              :  * @param[in,out] lh scrap context
     172              :  */
     173              : static void
     174            0 : free_scrap (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh)
     175              : {
     176              :   struct Scrap *s;
     177              : 
     178            0 :   while (NULL != (s = lh->scrap_head))
     179              :   {
     180            0 :     GNUNET_CONTAINER_DLL_remove (lh->scrap_head,
     181              :                                  lh->scrap_tail,
     182              :                                  s);
     183            0 :     GNUNET_free (s->ptr);
     184            0 :     GNUNET_free (s);
     185              :   }
     186            0 : }
     187              : 
     188              : 
     189              : /**
     190              :  * Convert JSON array of strings to string array.
     191              :  *
     192              :  * @param j JSON array to convert
     193              :  * @param[out] a array to initialize
     194              :  * @return true on success
     195              :  */
     196              : static bool
     197            0 : j_to_a (const json_t *j,
     198              :         const char **a)
     199              : {
     200              :   const json_t *e;
     201              :   size_t idx;
     202              : 
     203            0 :   json_array_foreach ((json_t *) j, idx, e)
     204              :   {
     205            0 :     if (NULL == (a[idx] = json_string_value (e)))
     206            0 :       return false;
     207              :   }
     208            0 :   return true;
     209              : }
     210              : 
     211              : 
     212              : /**
     213              :  * Parse AML programs.
     214              :  *
     215              :  * @param[in,out] lh context for allocations
     216              :  * @param jprogs JSON object with program data
     217              :  * @param[out] progs where to write the result
     218              :  * @return #GNUNET_OK on success
     219              :  */
     220              : static enum GNUNET_GenericReturnValue
     221            0 : parse_aml_programs (
     222              :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
     223              :   const json_t *jprogs,
     224              :   struct TALER_EXCHANGE_AvailableAmlPrograms *progs)
     225              : {
     226              :   const json_t *obj;
     227              :   const char *name;
     228            0 :   size_t idx = 0;
     229              : 
     230            0 :   json_object_foreach ((json_t *) jprogs, name, obj)
     231              :   {
     232            0 :     struct TALER_EXCHANGE_AvailableAmlPrograms *prog
     233            0 :       = &progs[idx++];
     234              :     const json_t *jcontext;
     235              :     const json_t *jinputs;
     236              :     struct GNUNET_JSON_Specification spec[] = {
     237            0 :       GNUNET_JSON_spec_string ("description",
     238              :                                &prog->description),
     239            0 :       GNUNET_JSON_spec_array_const ("context",
     240              :                                     &jcontext),
     241            0 :       GNUNET_JSON_spec_array_const ("inputs",
     242              :                                     &jinputs),
     243            0 :       GNUNET_JSON_spec_end ()
     244              :     };
     245              :     unsigned int len;
     246              :     const char **ptr;
     247              : 
     248            0 :     if (GNUNET_OK !=
     249            0 :         GNUNET_JSON_parse (obj,
     250              :                            spec,
     251              :                            NULL,
     252              :                            NULL))
     253              :     {
     254            0 :       GNUNET_break_op (0);
     255            0 :       return GNUNET_SYSERR;
     256              :     }
     257            0 :     prog->prog_name = name;
     258              :     prog->contexts_length
     259            0 :       = (unsigned int) json_array_size (jcontext);
     260              :     prog->inputs_length
     261            0 :       = (unsigned int) json_array_size (jinputs);
     262            0 :     len = prog->contexts_length + prog->inputs_length;
     263            0 :     if ( ((unsigned long long) len) !=
     264            0 :          (unsigned long long) json_array_size (jcontext)
     265            0 :          + (unsigned long long) json_array_size (jinputs) )
     266              :     {
     267            0 :       GNUNET_break_op (0);
     268            0 :       return GNUNET_SYSERR;
     269              :     }
     270            0 :     ptr = make_scrap (lh,
     271              :                       len);
     272            0 :     prog->contexts = ptr;
     273            0 :     if (! j_to_a (jcontext,
     274              :                   prog->contexts))
     275              :     {
     276            0 :       GNUNET_break_op (0);
     277            0 :       return GNUNET_SYSERR;
     278              :     }
     279            0 :     prog->inputs = &ptr[prog->contexts_length];
     280            0 :     if (! j_to_a (jinputs,
     281              :                   prog->inputs))
     282              :     {
     283            0 :       GNUNET_break_op (0);
     284            0 :       return GNUNET_SYSERR;
     285              :     }
     286              :   }
     287            0 :   return GNUNET_OK;
     288              : }
     289              : 
     290              : 
     291              : /**
     292              :  * Parse AML measures.
     293              :  *
     294              :  * @param[in,out] lh context for allocations
     295              :  * @param jchecks JSON object with measure data
     296              :  * @param[out] checks where to write the result
     297              :  * @return #GNUNET_OK on success
     298              :  */
     299              : static enum GNUNET_GenericReturnValue
     300            0 : parse_aml_checks (
     301              :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
     302              :   const json_t *jchecks,
     303              :   struct TALER_EXCHANGE_AvailableKycChecks *checks)
     304              : {
     305              :   const json_t *obj;
     306              :   const char *name;
     307            0 :   size_t idx = 0;
     308              : 
     309            0 :   json_object_foreach ((json_t *) jchecks, name, obj)
     310              :   {
     311            0 :     struct TALER_EXCHANGE_AvailableKycChecks *check
     312            0 :       = &checks[idx++];
     313              :     const json_t *jrequires;
     314              :     const json_t *joutputs;
     315              :     struct GNUNET_JSON_Specification spec[] = {
     316            0 :       GNUNET_JSON_spec_string ("description",
     317              :                                &check->description),
     318            0 :       GNUNET_JSON_spec_mark_optional (
     319              :         GNUNET_JSON_spec_object_const ("description_i18n",
     320              :                                        &check->description_i18n),
     321              :         NULL),
     322            0 :       GNUNET_JSON_spec_array_const ("requires",
     323              :                                     &jrequires),
     324            0 :       GNUNET_JSON_spec_array_const ("outputs",
     325              :                                     &joutputs),
     326            0 :       GNUNET_JSON_spec_string ("fallback",
     327              :                                &check->fallback),
     328            0 :       GNUNET_JSON_spec_end ()
     329              :     };
     330              :     unsigned int len;
     331              :     const char **ptr;
     332              : 
     333            0 :     if (GNUNET_OK !=
     334            0 :         GNUNET_JSON_parse (obj,
     335              :                            spec,
     336              :                            NULL,
     337              :                            NULL))
     338              :     {
     339            0 :       GNUNET_break_op (0);
     340            0 :       return GNUNET_SYSERR;
     341              :     }
     342            0 :     check->check_name = name;
     343              : 
     344              :     check->requires_length
     345            0 :       = (unsigned int) json_array_size (jrequires);
     346              :     check->outputs_length
     347            0 :       = (unsigned int) json_array_size (joutputs);
     348            0 :     len = check->requires_length + check->outputs_length;
     349            0 :     if ( ((unsigned long long) len) !=
     350            0 :          (unsigned long long) json_array_size (jrequires)
     351            0 :          + (unsigned long long) json_array_size (joutputs) )
     352              :     {
     353            0 :       GNUNET_break_op (0);
     354            0 :       return GNUNET_SYSERR;
     355              :     }
     356            0 :     ptr = make_scrap (lh,
     357              :                       len);
     358            0 :     check->requires = ptr;
     359            0 :     if (! j_to_a (jrequires,
     360              :                   check->requires))
     361              :     {
     362            0 :       GNUNET_break_op (0);
     363            0 :       return GNUNET_SYSERR;
     364              :     }
     365            0 :     check->outputs = &ptr[check->requires_length];
     366            0 :     if (! j_to_a (joutputs,
     367              :                   check->outputs))
     368              :     {
     369            0 :       GNUNET_break_op (0);
     370            0 :       return GNUNET_SYSERR;
     371              :     }
     372              :   }
     373            0 :   return GNUNET_OK;
     374              : }
     375              : 
     376              : 
     377              : /**
     378              :  * Parse the provided decision data from the "200 OK" response.
     379              :  *
     380              :  * @param[in,out] lh handle (callback may be zero'ed out)
     381              :  * @param json json reply with the data for one coin
     382              :  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
     383              :  */
     384              : static enum GNUNET_GenericReturnValue
     385            0 : parse_measures_ok (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
     386              :                    const json_t *json)
     387              : {
     388            0 :   struct TALER_EXCHANGE_AmlGetMeasuresResponse lr = {
     389              :     .hr.reply = json,
     390              :     .hr.http_status = MHD_HTTP_OK
     391              :   };
     392              :   const json_t *jroots;
     393              :   const json_t *jprograms;
     394              :   const json_t *jchecks;
     395              :   struct GNUNET_JSON_Specification spec[] = {
     396            0 :     GNUNET_JSON_spec_object_const ("roots",
     397              :                                    &jroots),
     398            0 :     GNUNET_JSON_spec_object_const ("programs",
     399              :                                    &jprograms),
     400            0 :     GNUNET_JSON_spec_object_const ("checks",
     401              :                                    &jchecks),
     402            0 :     GNUNET_JSON_spec_end ()
     403              :   };
     404              : 
     405            0 :   if (GNUNET_OK !=
     406            0 :       GNUNET_JSON_parse (json,
     407              :                          spec,
     408              :                          NULL,
     409              :                          NULL))
     410              :   {
     411            0 :     GNUNET_break_op (0);
     412            0 :     return GNUNET_SYSERR;
     413              :   }
     414              :   lr.details.ok.roots_length
     415            0 :     = (unsigned int) json_object_size (jroots);
     416              :   lr.details.ok.programs_length
     417            0 :     = (unsigned int) json_object_size (jprograms);
     418              :   lr.details.ok.checks_length
     419            0 :     = (unsigned int) json_object_size (jchecks);
     420            0 :   if ( ( ((size_t) lr.details.ok.roots_length)
     421            0 :          != json_object_size (jroots)) ||
     422            0 :        ( ((size_t) lr.details.ok.programs_length)
     423            0 :          != json_object_size (jprograms)) ||
     424            0 :        ( ((size_t) lr.details.ok.checks_length)
     425            0 :          != json_object_size (jchecks)) )
     426              :   {
     427            0 :     GNUNET_break_op (0);
     428            0 :     return GNUNET_SYSERR;
     429              :   }
     430              : 
     431            0 :   {
     432            0 :     struct TALER_EXCHANGE_AvailableAmlMeasures roots[
     433            0 :       GNUNET_NZL (lr.details.ok.roots_length)];
     434            0 :     struct TALER_EXCHANGE_AvailableAmlPrograms progs[
     435            0 :       GNUNET_NZL (lr.details.ok.programs_length)];
     436            0 :     struct TALER_EXCHANGE_AvailableKycChecks checks[
     437            0 :       GNUNET_NZL (lr.details.ok.checks_length)];
     438              :     enum GNUNET_GenericReturnValue ret;
     439              : 
     440            0 :     memset (roots,
     441              :             0,
     442              :             sizeof (roots));
     443            0 :     memset (progs,
     444              :             0,
     445              :             sizeof (progs));
     446            0 :     memset (checks,
     447              :             0,
     448              :             sizeof (checks));
     449            0 :     lr.details.ok.roots = roots;
     450            0 :     lr.details.ok.programs = progs;
     451            0 :     lr.details.ok.checks = checks;
     452            0 :     ret = parse_aml_roots (jroots,
     453              :                            roots);
     454            0 :     if (GNUNET_OK == ret)
     455            0 :       ret = parse_aml_programs (lh,
     456              :                                 jprograms,
     457              :                                 progs);
     458            0 :     if (GNUNET_OK == ret)
     459            0 :       ret = parse_aml_checks (lh,
     460              :                               jchecks,
     461              :                               checks);
     462            0 :     if (GNUNET_OK == ret)
     463              :     {
     464            0 :       lh->measures_cb (lh->measures_cb_cls,
     465              :                        &lr);
     466            0 :       lh->measures_cb = NULL;
     467              :     }
     468            0 :     free_scrap (lh);
     469            0 :     return ret;
     470              :   }
     471              : }
     472              : 
     473              : 
     474              : /**
     475              :  * Function called when we're done processing the
     476              :  * HTTP /aml/$OFFICER_PUB/measures request.
     477              :  *
     478              :  * @param cls the `struct TALER_EXCHANGE_AmlGetMeasuresHandle`
     479              :  * @param response_code HTTP response code, 0 on error
     480              :  * @param response parsed JSON result, NULL on error
     481              :  */
     482              : static void
     483            0 : handle_lookup_finished (void *cls,
     484              :                         long response_code,
     485              :                         const void *response)
     486              : {
     487            0 :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh = cls;
     488            0 :   const json_t *j = response;
     489            0 :   struct TALER_EXCHANGE_AmlGetMeasuresResponse lr = {
     490              :     .hr.reply = j,
     491            0 :     .hr.http_status = (unsigned int) response_code
     492              :   };
     493              : 
     494            0 :   lh->job = NULL;
     495            0 :   switch (response_code)
     496              :   {
     497            0 :   case 0:
     498            0 :     lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     499            0 :     break;
     500            0 :   case MHD_HTTP_OK:
     501            0 :     if (GNUNET_OK !=
     502            0 :         parse_measures_ok (lh,
     503              :                            j))
     504              :     {
     505            0 :       GNUNET_break_op (0);
     506            0 :       lr.hr.http_status = 0;
     507            0 :       lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     508            0 :       break;
     509              :     }
     510            0 :     GNUNET_assert (NULL == lh->measures_cb);
     511            0 :     TALER_EXCHANGE_aml_get_measures_cancel (lh);
     512            0 :     return;
     513            0 :   case MHD_HTTP_NO_CONTENT:
     514            0 :     break;
     515            0 :   case MHD_HTTP_BAD_REQUEST:
     516            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     517            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     518              :     /* This should never happen, either us or the exchange is buggy
     519              :        (or API version conflict); just pass JSON reply to the application */
     520            0 :     break;
     521            0 :   case MHD_HTTP_FORBIDDEN:
     522            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     523            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     524              :     /* Nothing really to verify, exchange says this coin was not melted; we
     525              :        should pass the JSON reply to the application */
     526            0 :     break;
     527            0 :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     528            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     529            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     530              :     /* Server had an internal issue; we should retry, but this API
     531              :        leaves this to the application */
     532            0 :     break;
     533            0 :   default:
     534              :     /* unexpected response code */
     535            0 :     GNUNET_break_op (0);
     536            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     537            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     538            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     539              :                 "Unexpected response code %u/%d for get AML measures\n",
     540              :                 (unsigned int) response_code,
     541              :                 (int) lr.hr.ec);
     542            0 :     break;
     543              :   }
     544            0 :   if (NULL != lh->measures_cb)
     545            0 :     lh->measures_cb (lh->measures_cb_cls,
     546              :                      &lr);
     547            0 :   TALER_EXCHANGE_aml_get_measures_cancel (lh);
     548              : }
     549              : 
     550              : 
     551              : struct TALER_EXCHANGE_AmlGetMeasuresHandle *
     552            0 : TALER_EXCHANGE_aml_get_measures (
     553              :   struct GNUNET_CURL_Context *ctx,
     554              :   const char *exchange_url,
     555              :   const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
     556              :   TALER_EXCHANGE_AmlMeasuresCallback cb,
     557              :   void *cb_cls)
     558              : {
     559              :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh;
     560              :   CURL *eh;
     561              :   struct TALER_AmlOfficerPublicKeyP officer_pub;
     562              :   struct TALER_AmlOfficerSignatureP officer_sig;
     563              :   char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2
     564              :                + 32];
     565              : 
     566            0 :   GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
     567              :                                       &officer_pub.eddsa_pub);
     568            0 :   TALER_officer_aml_query_sign (officer_priv,
     569              :                                 &officer_sig);
     570              :   {
     571              :     char pub_str[sizeof (officer_pub) * 2];
     572              :     char *end;
     573              : 
     574            0 :     end = GNUNET_STRINGS_data_to_string (
     575              :       &officer_pub,
     576              :       sizeof (officer_pub),
     577              :       pub_str,
     578              :       sizeof (pub_str));
     579            0 :     *end = '\0';
     580            0 :     GNUNET_snprintf (arg_str,
     581              :                      sizeof (arg_str),
     582              :                      "aml/%s/measures",
     583              :                      pub_str);
     584              :   }
     585            0 :   lh = GNUNET_new (struct TALER_EXCHANGE_AmlGetMeasuresHandle);
     586            0 :   lh->measures_cb = cb;
     587            0 :   lh->measures_cb_cls = cb_cls;
     588            0 :   lh->url = TALER_url_join (exchange_url,
     589              :                             arg_str,
     590              :                             NULL);
     591            0 :   if (NULL == lh->url)
     592              :   {
     593            0 :     GNUNET_free (lh);
     594            0 :     return NULL;
     595              :   }
     596            0 :   eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
     597            0 :   if (NULL == eh)
     598              :   {
     599            0 :     GNUNET_break (0);
     600            0 :     GNUNET_free (lh->url);
     601            0 :     GNUNET_free (lh);
     602            0 :     return NULL;
     603              :   }
     604              :   {
     605              :     char *hdr;
     606              :     char sig_str[sizeof (officer_sig) * 2];
     607              :     char *end;
     608              : 
     609            0 :     end = GNUNET_STRINGS_data_to_string (
     610              :       &officer_sig,
     611              :       sizeof (officer_sig),
     612              :       sig_str,
     613              :       sizeof (sig_str));
     614            0 :     *end = '\0';
     615              : 
     616            0 :     GNUNET_asprintf (&hdr,
     617              :                      "%s: %s",
     618              :                      TALER_AML_OFFICER_SIGNATURE_HEADER,
     619              :                      sig_str);
     620            0 :     lh->job_headers = curl_slist_append (NULL,
     621              :                                          hdr);
     622            0 :     GNUNET_free (hdr);
     623            0 :     lh->job_headers = curl_slist_append (lh->job_headers,
     624              :                                          "Content-type: application/json");
     625            0 :     lh->job = GNUNET_CURL_job_add2 (ctx,
     626              :                                     eh,
     627            0 :                                     lh->job_headers,
     628              :                                     &handle_lookup_finished,
     629              :                                     lh);
     630              :   }
     631            0 :   return lh;
     632              : }
     633              : 
     634              : 
     635              : void
     636            0 : TALER_EXCHANGE_aml_get_measures_cancel (
     637              :   struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh)
     638              : {
     639            0 :   if (NULL != lh->job)
     640              :   {
     641            0 :     GNUNET_CURL_job_cancel (lh->job);
     642            0 :     lh->job = NULL;
     643              :   }
     644            0 :   curl_slist_free_all (lh->job_headers);
     645            0 :   GNUNET_free (lh->url);
     646            0 :   GNUNET_free (lh);
     647            0 : }
     648              : 
     649              : 
     650              : /* end of exchange_api_get_aml_measures.c */
        

Generated by: LCOV version 2.0-1