LCOV - code coverage report
Current view: top level - lib - exchange_api_get-aml-OFFICER_PUB-measures.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 252 0
Test Date: 2026-03-10 12:10:57 Functions: 0.0 % 12 0

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2023, 2024, 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              :   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-OFFICER_PUB-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 "taler/taler-exchange/get-aml-OFFICER_PUB-measures.h"
      29              : #include "exchange_api_handle.h"
      30              : #include "taler/taler_signatures.h"
      31              : #include "exchange_api_curl_defaults.h"
      32              : 
      33              : 
      34              : /**
      35              :  * Scrap buffer of temporary arrays.
      36              :  */
      37              : struct Scrap
      38              : {
      39              :   /**
      40              :    * Kept in DLL.
      41              :    */
      42              :   struct Scrap *next;
      43              : 
      44              :   /**
      45              :    * Kept in DLL.
      46              :    */
      47              :   struct Scrap *prev;
      48              : 
      49              :   /**
      50              :    * Pointer to our allocation.
      51              :    */
      52              :   const char **ptr;
      53              : };
      54              : 
      55              : 
      56              : /**
      57              :  * @brief A GET /aml/$OFFICER_PUB/measures Handle
      58              :  */
      59              : struct TALER_EXCHANGE_GetAmlMeasuresHandle
      60              : {
      61              : 
      62              :   /**
      63              :    * The base URL of the exchange.
      64              :    */
      65              :   char *base_url;
      66              : 
      67              :   /**
      68              :    * The full URL for this request, set during _start.
      69              :    */
      70              :   char *url;
      71              : 
      72              :   /**
      73              :    * Handle for the request.
      74              :    */
      75              :   struct GNUNET_CURL_Job *job;
      76              : 
      77              :   /**
      78              :    * Function to call with the result.
      79              :    */
      80              :   TALER_EXCHANGE_GetAmlMeasuresCallback cb;
      81              : 
      82              :   /**
      83              :    * Closure for @e cb.
      84              :    */
      85              :   TALER_EXCHANGE_GET_AML_MEASURES_RESULT_CLOSURE *cb_cls;
      86              : 
      87              :   /**
      88              :    * Reference to the execution context.
      89              :    */
      90              :   struct GNUNET_CURL_Context *ctx;
      91              : 
      92              :   /**
      93              :    * Public key of the AML officer.
      94              :    */
      95              :   struct TALER_AmlOfficerPublicKeyP officer_pub;
      96              : 
      97              :   /**
      98              :    * Private key of the AML officer (for signing).
      99              :    */
     100              :   struct TALER_AmlOfficerPrivateKeyP officer_priv;
     101              : 
     102              :   /**
     103              :    * Head of scrap list.
     104              :    */
     105              :   struct Scrap *scrap_head;
     106              : 
     107              :   /**
     108              :    * Tail of scrap list.
     109              :    */
     110              :   struct Scrap *scrap_tail;
     111              : };
     112              : 
     113              : 
     114              : /**
     115              :  * Create array of length @a len in scrap book.
     116              :  *
     117              :  * @param[in,out] amh context for allocations
     118              :  * @param len length of array
     119              :  * @return scrap array
     120              :  */
     121              : static const char **
     122            0 : make_scrap (
     123              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     124              :   unsigned int len)
     125              : {
     126            0 :   struct Scrap *s = GNUNET_new (struct Scrap);
     127              : 
     128            0 :   s->ptr = GNUNET_new_array (len,
     129              :                              const char *);
     130            0 :   GNUNET_CONTAINER_DLL_insert (amh->scrap_head,
     131              :                                amh->scrap_tail,
     132              :                                s);
     133            0 :   return s->ptr;
     134              : }
     135              : 
     136              : 
     137              : /**
     138              :  * Free all scrap space.
     139              :  *
     140              :  * @param[in,out] amh scrap context
     141              :  */
     142              : static void
     143            0 : free_scrap (struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh)
     144              : {
     145              :   struct Scrap *s;
     146              : 
     147            0 :   while (NULL != (s = amh->scrap_head))
     148              :   {
     149            0 :     GNUNET_CONTAINER_DLL_remove (amh->scrap_head,
     150              :                                  amh->scrap_tail,
     151              :                                  s);
     152            0 :     GNUNET_free (s->ptr);
     153            0 :     GNUNET_free (s);
     154              :   }
     155            0 : }
     156              : 
     157              : 
     158              : /**
     159              :  * Convert JSON array of strings to string array.
     160              :  *
     161              :  * @param j JSON array to convert
     162              :  * @param[out] a array to initialize
     163              :  * @return true on success
     164              :  */
     165              : static bool
     166            0 : j_to_a (const json_t *j,
     167              :         const char **a)
     168              : {
     169              :   const json_t *e;
     170              :   size_t idx;
     171              : 
     172            0 :   json_array_foreach ((json_t *) j, idx, e)
     173              :   {
     174            0 :     if (NULL == (a[idx] = json_string_value (e)))
     175            0 :       return false;
     176              :   }
     177            0 :   return true;
     178              : }
     179              : 
     180              : 
     181              : /**
     182              :  * Parse AML root measures.
     183              :  *
     184              :  * @param jroots JSON object with measure data
     185              :  * @param[out] roots where to write the result
     186              :  * @return #GNUNET_OK on success
     187              :  */
     188              : static enum GNUNET_GenericReturnValue
     189            0 : parse_aml_roots (
     190              :   const json_t *jroots,
     191              :   struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo *roots)
     192              : {
     193              :   const json_t *obj;
     194              :   const char *name;
     195            0 :   size_t idx = 0;
     196              : 
     197            0 :   json_object_foreach ((json_t *) jroots, name, obj)
     198              :   {
     199            0 :     struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo *root = &roots[idx++];
     200              :     struct GNUNET_JSON_Specification spec[] = {
     201            0 :       GNUNET_JSON_spec_string ("check_name",
     202              :                                &root->check_name),
     203            0 :       GNUNET_JSON_spec_mark_optional (
     204              :         GNUNET_JSON_spec_string ("prog_name",
     205              :                                  &root->prog_name),
     206              :         NULL),
     207            0 :       GNUNET_JSON_spec_mark_optional (
     208              :         GNUNET_JSON_spec_object_const ("context",
     209              :                                        &root->context),
     210              :         NULL),
     211            0 :       GNUNET_JSON_spec_mark_optional (
     212              :         GNUNET_JSON_spec_string ("operation_type",
     213              :                                  &root->operation_type),
     214              :         NULL),
     215            0 :       GNUNET_JSON_spec_mark_optional (
     216              :         GNUNET_JSON_spec_bool ("voluntary",
     217              :                                &root->voluntary),
     218              :         NULL),
     219            0 :       GNUNET_JSON_spec_end ()
     220              :     };
     221              : 
     222            0 :     if (GNUNET_OK !=
     223            0 :         GNUNET_JSON_parse (obj,
     224              :                            spec,
     225              :                            NULL,
     226              :                            NULL))
     227              :     {
     228            0 :       GNUNET_break_op (0);
     229            0 :       return GNUNET_SYSERR;
     230              :     }
     231            0 :     root->measure_name = name;
     232              :   }
     233            0 :   return GNUNET_OK;
     234              : }
     235              : 
     236              : 
     237              : /**
     238              :  * Parse AML programs.
     239              :  *
     240              :  * @param[in,out] amh context for allocations
     241              :  * @param jprogs JSON object with program data
     242              :  * @param[out] progs where to write the result
     243              :  * @return #GNUNET_OK on success
     244              :  */
     245              : static enum GNUNET_GenericReturnValue
     246            0 : parse_aml_programs (
     247              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     248              :   const json_t *jprogs,
     249              :   struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement *progs)
     250              : {
     251              :   const json_t *obj;
     252              :   const char *name;
     253            0 :   size_t idx = 0;
     254              : 
     255            0 :   json_object_foreach ((json_t *) jprogs, name, obj)
     256              :   {
     257            0 :     struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement *prog = &progs[idx++]
     258              :     ;
     259              :     const json_t *jcontext;
     260              :     const json_t *jinputs;
     261              :     struct GNUNET_JSON_Specification spec[] = {
     262            0 :       GNUNET_JSON_spec_string ("description",
     263              :                                &prog->description),
     264            0 :       GNUNET_JSON_spec_array_const ("context",
     265              :                                     &jcontext),
     266            0 :       GNUNET_JSON_spec_array_const ("inputs",
     267              :                                     &jinputs),
     268            0 :       GNUNET_JSON_spec_end ()
     269              :     };
     270              :     unsigned int len;
     271              :     const char **ptr;
     272              : 
     273            0 :     if (GNUNET_OK !=
     274            0 :         GNUNET_JSON_parse (obj,
     275              :                            spec,
     276              :                            NULL,
     277              :                            NULL))
     278              :     {
     279            0 :       GNUNET_break_op (0);
     280            0 :       return GNUNET_SYSERR;
     281              :     }
     282            0 :     prog->prog_name = name;
     283            0 :     prog->contexts_length = json_array_size (jcontext);
     284            0 :     prog->inputs_length = json_array_size (jinputs);
     285            0 :     len = (unsigned int) (prog->contexts_length + prog->inputs_length);
     286            0 :     if ( ((size_t) len) != prog->contexts_length + prog->inputs_length)
     287              :     {
     288            0 :       GNUNET_break_op (0);
     289            0 :       return GNUNET_SYSERR;
     290              :     }
     291            0 :     ptr = make_scrap (amh, len);
     292            0 :     prog->contexts = ptr;
     293            0 :     if (! j_to_a (jcontext, prog->contexts))
     294              :     {
     295            0 :       GNUNET_break_op (0);
     296            0 :       return GNUNET_SYSERR;
     297              :     }
     298            0 :     prog->inputs = &ptr[prog->contexts_length];
     299            0 :     if (! j_to_a (jinputs, prog->inputs))
     300              :     {
     301            0 :       GNUNET_break_op (0);
     302            0 :       return GNUNET_SYSERR;
     303              :     }
     304              :   }
     305            0 :   return GNUNET_OK;
     306              : }
     307              : 
     308              : 
     309              : /**
     310              :  * Parse KYC checks.
     311              :  *
     312              :  * @param[in,out] amh context for allocations
     313              :  * @param jchecks JSON object with check data
     314              :  * @param[out] checks where to write the result
     315              :  * @return #GNUNET_OK on success
     316              :  */
     317              : static enum GNUNET_GenericReturnValue
     318            0 : parse_aml_checks (
     319              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     320              :   const json_t *jchecks,
     321              :   struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo *checks)
     322              : {
     323              :   const json_t *obj;
     324              :   const char *name;
     325            0 :   size_t idx = 0;
     326              : 
     327            0 :   json_object_foreach ((json_t *) jchecks, name, obj)
     328              :   {
     329            0 :     struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo *check = &checks[idx++];
     330              :     const json_t *jrequires;
     331              :     const json_t *joutputs;
     332              :     struct GNUNET_JSON_Specification spec[] = {
     333            0 :       GNUNET_JSON_spec_string ("description",
     334              :                                &check->description),
     335            0 :       GNUNET_JSON_spec_mark_optional (
     336              :         GNUNET_JSON_spec_object_const ("description_i18n",
     337              :                                        &check->description_i18n),
     338              :         NULL),
     339            0 :       GNUNET_JSON_spec_array_const ("requires",
     340              :                                     &jrequires),
     341            0 :       GNUNET_JSON_spec_array_const ("outputs",
     342              :                                     &joutputs),
     343            0 :       GNUNET_JSON_spec_string ("fallback",
     344              :                                &check->fallback),
     345            0 :       GNUNET_JSON_spec_end ()
     346              :     };
     347              :     unsigned int len;
     348              :     const char **ptr;
     349              : 
     350            0 :     if (GNUNET_OK !=
     351            0 :         GNUNET_JSON_parse (obj,
     352              :                            spec,
     353              :                            NULL,
     354              :                            NULL))
     355              :     {
     356            0 :       GNUNET_break_op (0);
     357            0 :       return GNUNET_SYSERR;
     358              :     }
     359            0 :     check->check_name = name;
     360            0 :     check->requires_length = json_array_size (jrequires);
     361            0 :     check->outputs_length = json_array_size (joutputs);
     362            0 :     len = (unsigned int) (check->requires_length + check->outputs_length);
     363            0 :     if ( ((size_t) len) != check->requires_length + check->outputs_length)
     364              :     {
     365            0 :       GNUNET_break_op (0);
     366            0 :       return GNUNET_SYSERR;
     367              :     }
     368            0 :     ptr = make_scrap (amh, len);
     369            0 :     check->requires = ptr;
     370            0 :     if (! j_to_a (jrequires, check->requires))
     371              :     {
     372            0 :       GNUNET_break_op (0);
     373            0 :       return GNUNET_SYSERR;
     374              :     }
     375            0 :     check->outputs = &ptr[check->requires_length];
     376            0 :     if (! j_to_a (joutputs, check->outputs))
     377              :     {
     378            0 :       GNUNET_break_op (0);
     379            0 :       return GNUNET_SYSERR;
     380              :     }
     381              :   }
     382            0 :   return GNUNET_OK;
     383              : }
     384              : 
     385              : 
     386              : /**
     387              :  * Parse default KYC rules from the default_rules array.
     388              :  *
     389              :  * @param[in,out] amh context for allocations
     390              :  * @param jrules JSON array with rule data
     391              :  * @param[out] rules where to write the result
     392              :  * @return #GNUNET_OK on success
     393              :  */
     394              : static enum GNUNET_GenericReturnValue
     395            0 : parse_default_rules (
     396              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     397              :   const json_t *jrules,
     398              :   struct TALER_EXCHANGE_GetAmlMeasuresKycRule *rules)
     399              : {
     400              :   const json_t *obj;
     401              :   size_t idx;
     402              : 
     403            0 :   json_array_foreach ((json_t *) jrules, idx, obj)
     404              :   {
     405            0 :     struct TALER_EXCHANGE_GetAmlMeasuresKycRule *rule = &rules[idx];
     406              :     const json_t *jmeasures;
     407              :     struct GNUNET_JSON_Specification spec[] = {
     408            0 :       TALER_JSON_spec_kycte ("operation_type",
     409              :                              &rule->operation_type),
     410            0 :       GNUNET_JSON_spec_mark_optional (
     411              :         GNUNET_JSON_spec_string ("rule_name",
     412              :                                  &rule->rule_name),
     413              :         NULL),
     414            0 :       TALER_JSON_spec_amount_any ("threshold",
     415              :                                   &rule->threshold),
     416            0 :       GNUNET_JSON_spec_relative_time ("timeframe",
     417              :                                       &rule->timeframe),
     418            0 :       GNUNET_JSON_spec_array_const ("measures",
     419              :                                     &jmeasures),
     420            0 :       GNUNET_JSON_spec_mark_optional (
     421              :         GNUNET_JSON_spec_bool ("exposed",
     422              :                                &rule->exposed),
     423              :         NULL),
     424            0 :       GNUNET_JSON_spec_mark_optional (
     425              :         GNUNET_JSON_spec_bool ("is_and_combinator",
     426              :                                &rule->is_and_combinator),
     427              :         NULL),
     428            0 :       GNUNET_JSON_spec_int64 ("display_priority",
     429              :                               &rule->display_priority),
     430            0 :       GNUNET_JSON_spec_end ()
     431              :     };
     432              : 
     433            0 :     if (GNUNET_OK !=
     434            0 :         GNUNET_JSON_parse (obj,
     435              :                            spec,
     436              :                            NULL,
     437              :                            NULL))
     438              :     {
     439            0 :       GNUNET_break_op (0);
     440            0 :       return GNUNET_SYSERR;
     441              :     }
     442            0 :     rule->measures_length = json_array_size (jmeasures);
     443              :     {
     444            0 :       const char **ptr = make_scrap (amh,
     445            0 :                                      (unsigned int) rule->measures_length);
     446              : 
     447            0 :       rule->measures = ptr;
     448            0 :       if (! j_to_a (jmeasures,
     449              :                     ptr))
     450              :       {
     451            0 :         GNUNET_break_op (0);
     452            0 :         return GNUNET_SYSERR;
     453              :       }
     454              :     }
     455              :   }
     456            0 :   return GNUNET_OK;
     457              : }
     458              : 
     459              : 
     460              : /**
     461              :  * Parse the provided measures data from the "200 OK" response.
     462              :  *
     463              :  * @param[in,out] amh handle (callback may be zero'ed out)
     464              :  * @param json json reply with the data
     465              :  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
     466              :  */
     467              : static enum GNUNET_GenericReturnValue
     468            0 : parse_get_aml_measures_ok (struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     469              :                            const json_t *json)
     470              : {
     471            0 :   struct TALER_EXCHANGE_GetAmlMeasuresResponse lr = {
     472              :     .hr.reply = json,
     473              :     .hr.http_status = MHD_HTTP_OK
     474              :   };
     475              :   const json_t *jroots;
     476              :   const json_t *jprograms;
     477              :   const json_t *jchecks;
     478            0 :   const json_t *jdefault_rules = NULL;
     479              :   struct GNUNET_JSON_Specification spec[] = {
     480            0 :     GNUNET_JSON_spec_object_const ("roots",
     481              :                                    &jroots),
     482            0 :     GNUNET_JSON_spec_object_const ("programs",
     483              :                                    &jprograms),
     484            0 :     GNUNET_JSON_spec_object_const ("checks",
     485              :                                    &jchecks),
     486            0 :     GNUNET_JSON_spec_mark_optional (
     487              :       GNUNET_JSON_spec_array_const ("default_rules",
     488              :                                     &jdefault_rules),
     489              :       NULL),
     490            0 :     GNUNET_JSON_spec_end ()
     491              :   };
     492              : 
     493            0 :   if (GNUNET_OK !=
     494            0 :       GNUNET_JSON_parse (json,
     495              :                          spec,
     496              :                          NULL,
     497              :                          NULL))
     498              :   {
     499            0 :     GNUNET_break_op (0);
     500            0 :     return GNUNET_SYSERR;
     501              :   }
     502              : 
     503            0 :   lr.details.ok.roots_length = json_object_size (jroots);
     504            0 :   lr.details.ok.programs_length = json_object_size (jprograms);
     505            0 :   lr.details.ok.checks_length = json_object_size (jchecks);
     506            0 :   lr.details.ok.default_rules_length =
     507            0 :     (NULL != jdefault_rules) ? json_array_size (jdefault_rules) : 0;
     508              : 
     509            0 :   {
     510            0 :     struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo roots[
     511            0 :       GNUNET_NZL (lr.details.ok.roots_length)];
     512            0 :     struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement progs[
     513            0 :       GNUNET_NZL (lr.details.ok.programs_length)];
     514            0 :     struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo checks[
     515            0 :       GNUNET_NZL (lr.details.ok.checks_length)];
     516            0 :     struct TALER_EXCHANGE_GetAmlMeasuresKycRule drules[
     517            0 :       GNUNET_NZL (lr.details.ok.default_rules_length)];
     518              :     enum GNUNET_GenericReturnValue ret;
     519              : 
     520            0 :     memset (roots, 0, sizeof (roots));
     521            0 :     memset (progs, 0, sizeof (progs));
     522            0 :     memset (checks, 0, sizeof (checks));
     523            0 :     memset (drules, 0, sizeof (drules));
     524            0 :     lr.details.ok.roots = roots;
     525            0 :     lr.details.ok.programs = progs;
     526            0 :     lr.details.ok.checks = checks;
     527            0 :     lr.details.ok.default_rules = drules;
     528              : 
     529            0 :     ret = parse_aml_roots (jroots, roots);
     530            0 :     if (GNUNET_OK == ret)
     531            0 :       ret = parse_aml_programs (amh, jprograms, progs);
     532            0 :     if (GNUNET_OK == ret)
     533            0 :       ret = parse_aml_checks (amh, jchecks, checks);
     534            0 :     if ( (GNUNET_OK == ret) && (NULL != jdefault_rules) )
     535            0 :       ret = parse_default_rules (amh, jdefault_rules, drules);
     536            0 :     if (GNUNET_OK == ret)
     537              :     {
     538            0 :       amh->cb (amh->cb_cls,
     539              :                &lr);
     540            0 :       amh->cb = NULL;
     541              :     }
     542            0 :     free_scrap (amh);
     543            0 :     return ret;
     544              :   }
     545              : }
     546              : 
     547              : 
     548              : /**
     549              :  * Function called when we're done processing the
     550              :  * HTTP GET /aml/$OFFICER_PUB/measures request.
     551              :  *
     552              :  * @param cls the `struct TALER_EXCHANGE_GetAmlMeasuresHandle`
     553              :  * @param response_code HTTP response code, 0 on error
     554              :  * @param response parsed JSON result, NULL on error
     555              :  */
     556              : static void
     557            0 : handle_get_aml_measures_finished (void *cls,
     558              :                                   long response_code,
     559              :                                   const void *response)
     560              : {
     561            0 :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh = cls;
     562            0 :   const json_t *j = response;
     563            0 :   struct TALER_EXCHANGE_GetAmlMeasuresResponse lr = {
     564              :     .hr.reply = j,
     565            0 :     .hr.http_status = (unsigned int) response_code
     566              :   };
     567              : 
     568            0 :   amh->job = NULL;
     569            0 :   switch (response_code)
     570              :   {
     571            0 :   case 0:
     572            0 :     lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     573            0 :     break;
     574            0 :   case MHD_HTTP_OK:
     575            0 :     if (GNUNET_OK !=
     576            0 :         parse_get_aml_measures_ok (amh,
     577              :                                    j))
     578              :     {
     579            0 :       GNUNET_break_op (0);
     580            0 :       lr.hr.http_status = 0;
     581            0 :       lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     582            0 :       break;
     583              :     }
     584            0 :     GNUNET_assert (NULL == amh->cb);
     585            0 :     TALER_EXCHANGE_get_aml_measures_cancel (amh);
     586            0 :     return;
     587            0 :   case MHD_HTTP_NO_CONTENT:
     588            0 :     break;
     589            0 :   case MHD_HTTP_BAD_REQUEST:
     590            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     591            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     592            0 :     break;
     593            0 :   case MHD_HTTP_FORBIDDEN:
     594            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     595            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     596            0 :     break;
     597            0 :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     598            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     599            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     600            0 :     break;
     601            0 :   default:
     602              :     /* unexpected response code */
     603            0 :     GNUNET_break_op (0);
     604            0 :     lr.hr.ec = TALER_JSON_get_error_code (j);
     605            0 :     lr.hr.hint = TALER_JSON_get_error_hint (j);
     606            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     607              :                 "Unexpected response code %u/%d for GET AML measures\n",
     608              :                 (unsigned int) response_code,
     609              :                 (int) lr.hr.ec);
     610            0 :     break;
     611              :   }
     612            0 :   if (NULL != amh->cb)
     613            0 :     amh->cb (amh->cb_cls,
     614              :              &lr);
     615            0 :   TALER_EXCHANGE_get_aml_measures_cancel (amh);
     616              : }
     617              : 
     618              : 
     619              : struct TALER_EXCHANGE_GetAmlMeasuresHandle *
     620            0 : TALER_EXCHANGE_get_aml_measures_create (
     621              :   struct GNUNET_CURL_Context *ctx,
     622              :   const char *url,
     623              :   const struct TALER_AmlOfficerPrivateKeyP *officer_priv)
     624              : {
     625              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh;
     626              : 
     627            0 :   amh = GNUNET_new (struct TALER_EXCHANGE_GetAmlMeasuresHandle);
     628            0 :   amh->ctx = ctx;
     629            0 :   amh->base_url = GNUNET_strdup (url);
     630            0 :   amh->officer_priv = *officer_priv;
     631            0 :   GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
     632              :                                       &amh->officer_pub.eddsa_pub);
     633            0 :   return amh;
     634              : }
     635              : 
     636              : 
     637              : enum TALER_ErrorCode
     638            0 : TALER_EXCHANGE_get_aml_measures_start (
     639              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
     640              :   TALER_EXCHANGE_GetAmlMeasuresCallback cb,
     641              :   TALER_EXCHANGE_GET_AML_MEASURES_RESULT_CLOSURE *cb_cls)
     642              : {
     643              :   CURL *eh;
     644              :   struct TALER_AmlOfficerSignatureP officer_sig;
     645              :   char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 32];
     646            0 :   struct curl_slist *job_headers = NULL;
     647              : 
     648            0 :   amh->cb = cb;
     649            0 :   amh->cb_cls = cb_cls;
     650              : 
     651              :   /* Build AML officer signature */
     652            0 :   TALER_officer_aml_query_sign (&amh->officer_priv,
     653              :                                 &officer_sig);
     654              : 
     655              :   /* Build the path component: aml/{officer_pub}/measures */
     656              :   {
     657              :     char pub_str[sizeof (amh->officer_pub) * 2];
     658              :     char *end;
     659              : 
     660            0 :     end = GNUNET_STRINGS_data_to_string (
     661            0 :       &amh->officer_pub,
     662              :       sizeof (amh->officer_pub),
     663              :       pub_str,
     664              :       sizeof (pub_str));
     665            0 :     *end = '\0';
     666            0 :     GNUNET_snprintf (arg_str,
     667              :                      sizeof (arg_str),
     668              :                      "aml/%s/measures",
     669              :                      pub_str);
     670              :   }
     671              : 
     672            0 :   amh->url = TALER_url_join (amh->base_url,
     673              :                              arg_str,
     674              :                              NULL);
     675            0 :   if (NULL == amh->url)
     676            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     677              : 
     678            0 :   eh = TALER_EXCHANGE_curl_easy_get_ (amh->url);
     679            0 :   if (NULL == eh)
     680              :   {
     681            0 :     GNUNET_break (0);
     682            0 :     GNUNET_free (amh->url);
     683            0 :     amh->url = NULL;
     684            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     685              :   }
     686              : 
     687              :   /* Build job headers with AML officer signature */
     688              :   {
     689              :     char *hdr;
     690              :     char sig_str[sizeof (officer_sig) * 2];
     691              :     char *end;
     692              : 
     693            0 :     end = GNUNET_STRINGS_data_to_string (
     694              :       &officer_sig,
     695              :       sizeof (officer_sig),
     696              :       sig_str,
     697              :       sizeof (sig_str));
     698            0 :     *end = '\0';
     699              : 
     700            0 :     GNUNET_asprintf (&hdr,
     701              :                      "%s: %s",
     702              :                      TALER_AML_OFFICER_SIGNATURE_HEADER,
     703              :                      sig_str);
     704            0 :     job_headers = curl_slist_append (NULL,
     705              :                                      hdr);
     706            0 :     GNUNET_free (hdr);
     707            0 :     job_headers = curl_slist_append (job_headers,
     708              :                                      "Content-Type: application/json");
     709              :   }
     710              : 
     711            0 :   amh->job = GNUNET_CURL_job_add2 (amh->ctx,
     712              :                                    eh,
     713              :                                    job_headers,
     714              :                                    &handle_get_aml_measures_finished,
     715              :                                    amh);
     716            0 :   curl_slist_free_all (job_headers);
     717              : 
     718            0 :   if (NULL == amh->job)
     719              :   {
     720            0 :     GNUNET_free (amh->url);
     721            0 :     amh->url = NULL;
     722            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     723              :   }
     724            0 :   return TALER_EC_NONE;
     725              : }
     726              : 
     727              : 
     728              : void
     729            0 : TALER_EXCHANGE_get_aml_measures_cancel (
     730              :   struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh)
     731              : {
     732            0 :   if (NULL != amh->job)
     733              :   {
     734            0 :     GNUNET_CURL_job_cancel (amh->job);
     735            0 :     amh->job = NULL;
     736              :   }
     737            0 :   free_scrap (amh);
     738            0 :   GNUNET_free (amh->url);
     739            0 :   GNUNET_free (amh->base_url);
     740            0 :   GNUNET_free (amh);
     741            0 : }
     742              : 
     743              : 
     744              : /* end of exchange_api_get-aml-OFFICER_PUB-measures.c */
        

Generated by: LCOV version 2.0-1