LCOV - code coverage report
Current view: top level - bank-lib - taler-exchange-wire-gateway-client.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 47.8 % 312 149
Test Date: 2026-02-16 10:50:18 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2017-2023 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 <http://www.gnu.org/licenses/>
      15              : */
      16              : /**
      17              :  * @file taler-exchange-wire-gateway-client.c
      18              :  * @brief Execute wire transfer.
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "taler/platform.h"
      22              : #include <gnunet/gnunet_util_lib.h>
      23              : #include <gnunet/gnunet_json_lib.h>
      24              : #include <jansson.h>
      25              : #include <microhttpd.h>
      26              : #include "taler/taler_bank_service.h"
      27              : 
      28              : /**
      29              :  * If set to #GNUNET_YES, then we'll ask the bank for a list
      30              :  * of incoming transactions from the account.
      31              :  */
      32              : static int incoming_history;
      33              : 
      34              : /**
      35              :  * If set to #GNUNET_YES, then we'll ask the bank for a list
      36              :  * of outgoing transactions from the account.
      37              :  */
      38              : static int outgoing_history;
      39              : 
      40              : /**
      41              :  * Amount to transfer.
      42              :  */
      43              : static struct TALER_Amount amount;
      44              : 
      45              : /**
      46              :  * Credit account payto://-URI.
      47              :  */
      48              : static struct TALER_FullPayto credit_account;
      49              : 
      50              : /**
      51              :  * Debit account payto://-URI.
      52              :  */
      53              : static struct TALER_FullPayto debit_account;
      54              : 
      55              : /**
      56              :  * Wire transfer subject.
      57              :  */
      58              : static char *subject;
      59              : 
      60              : /**
      61              :  * Which config section has the credentials to access the bank.
      62              :  */
      63              : static char *account_section;
      64              : 
      65              : /**
      66              :  * Starting row.
      67              :  */
      68              : static unsigned long long start_row = UINT64_MAX;
      69              : 
      70              : /**
      71              :  * Authentication data.
      72              :  */
      73              : static struct TALER_BANK_AuthenticationData auth;
      74              : 
      75              : /**
      76              :  * Return value from main().
      77              :  */
      78              : static int global_ret = 1;
      79              : 
      80              : /**
      81              :  * Main execution context for the main loop.
      82              :  */
      83              : static struct GNUNET_CURL_Context *ctx;
      84              : 
      85              : /**
      86              :  * Handle to ongoing credit history operation.
      87              :  */
      88              : static struct TALER_BANK_CreditHistoryHandle *chh;
      89              : 
      90              : /**
      91              :  * Handle to ongoing debit history operation.
      92              :  */
      93              : static struct TALER_BANK_DebitHistoryHandle *dhh;
      94              : 
      95              : /**
      96              :  * Handle to fetch an access token.
      97              :  */
      98              : static struct TALER_BANK_AccountTokenHandle *ath;
      99              : 
     100              : /**
     101              :  * Handle for executing the wire transfer.
     102              :  */
     103              : static struct TALER_BANK_TransferHandle *eh;
     104              : 
     105              : /**
     106              :  * Handle to access the exchange.
     107              :  */
     108              : static struct TALER_BANK_AdminAddIncomingHandle *op;
     109              : 
     110              : /**
     111              :  * Context for running the CURL event loop.
     112              :  */
     113              : static struct GNUNET_CURL_RescheduleContext *rc;
     114              : 
     115              : 
     116              : /**
     117              :  * Function run when the test terminates (good or bad).
     118              :  * Cleans up our state.
     119              :  *
     120              :  * @param cls NULL
     121              :  */
     122              : static void
     123            4 : do_shutdown (void *cls)
     124              : {
     125              :   (void) cls;
     126            4 :   if (NULL != op)
     127              :   {
     128            0 :     TALER_BANK_admin_add_incoming_cancel (op);
     129            0 :     op = NULL;
     130              :   }
     131            4 :   if (NULL != chh)
     132              :   {
     133            0 :     TALER_BANK_credit_history_cancel (chh);
     134            0 :     chh = NULL;
     135              :   }
     136            4 :   if (NULL != dhh)
     137              :   {
     138            0 :     TALER_BANK_debit_history_cancel (dhh);
     139            0 :     dhh = NULL;
     140              :   }
     141            4 :   if (NULL != ath)
     142              :   {
     143            0 :     TALER_BANK_account_token_cancel (ath);
     144            0 :     ath = NULL;
     145              :   }
     146            4 :   if (NULL != eh)
     147              :   {
     148            0 :     TALER_BANK_transfer_cancel (eh);
     149            0 :     eh = NULL;
     150              :   }
     151            4 :   if (NULL != ctx)
     152              :   {
     153            4 :     GNUNET_CURL_fini (ctx);
     154            4 :     ctx = NULL;
     155              :   }
     156            4 :   if (NULL != rc)
     157              :   {
     158            4 :     GNUNET_CURL_gnunet_rc_destroy (rc);
     159            4 :     rc = NULL;
     160              :   }
     161            4 :   TALER_BANK_auth_free (&auth);
     162            4 : }
     163              : 
     164              : 
     165              : /**
     166              :  * Callback used to process the transaction
     167              :  * history returned by the bank.
     168              :  *
     169              :  * @param cls closure
     170              :  * @param reply response we got from the bank
     171              :  */
     172              : static void
     173            1 : credit_history_cb (void *cls,
     174              :                    const struct TALER_BANK_CreditHistoryResponse *reply)
     175              : {
     176              :   (void) cls;
     177              : 
     178            1 :   chh = NULL;
     179            1 :   switch (reply->http_status)
     180              :   {
     181            0 :   case 0:
     182            0 :     fprintf (stderr,
     183              :              "Failed to obtain HTTP reply from `%s'\n",
     184              :              auth.wire_gateway_url);
     185            0 :     global_ret = 2;
     186            0 :     break;
     187            0 :   case MHD_HTTP_NO_CONTENT:
     188            0 :     fprintf (stdout,
     189              :              "No transactions.\n");
     190            0 :     global_ret = 0;
     191            0 :     break;
     192            1 :   case MHD_HTTP_OK:
     193            2 :     for (unsigned int i = 0; i<reply->details.ok.details_length; i++)
     194              :     {
     195            1 :       const struct TALER_BANK_CreditDetails *cd =
     196            1 :         &reply->details.ok.details[i];
     197              : 
     198              :       /* If credit/debit accounts were specified, use as a filter */
     199            1 :       if ( (NULL != credit_account.full_payto) &&
     200            0 :            (0 != TALER_full_payto_cmp (credit_account,
     201              :                                        reply->details.ok.credit_account_uri) ) )
     202            0 :         continue;
     203            1 :       if ( (NULL != debit_account.full_payto) &&
     204            0 :            (0 != TALER_full_payto_cmp (debit_account,
     205              :                                        cd->debit_account_uri) ) )
     206            0 :         continue;
     207            1 :       switch (cd->type)
     208              :       {
     209            1 :       case TALER_BANK_CT_RESERVE:
     210            1 :         fprintf (stdout,
     211              :                  "%llu: %s->%s (%s) over %s at %s\n",
     212            1 :                  (unsigned long long) cd->serial_id,
     213            1 :                  cd->debit_account_uri.full_payto,
     214            1 :                  reply->details.ok.credit_account_uri.full_payto,
     215            1 :                  TALER_B2S (&cd->details.reserve.reserve_pub),
     216              :                  TALER_amount2s (&cd->amount),
     217              :                  GNUNET_TIME_timestamp2s (cd->execution_date));
     218            1 :         break;
     219            0 :       case TALER_BANK_CT_KYCAUTH:
     220            0 :         fprintf (stdout,
     221              :                  "%llu: %s->%s (KYC:%s) over %s at %s\n",
     222            0 :                  (unsigned long long) cd->serial_id,
     223            0 :                  cd->debit_account_uri.full_payto,
     224            0 :                  reply->details.ok.credit_account_uri.full_payto,
     225            0 :                  TALER_B2S (&cd->details.kycauth.account_pub),
     226              :                  TALER_amount2s (&cd->amount),
     227              :                  GNUNET_TIME_timestamp2s (cd->execution_date));
     228            0 :         break;
     229            0 :       case TALER_BANK_CT_WAD:
     230            0 :         GNUNET_break (0); // FIXME-#7271 (support wad payments)
     231            0 :         break;
     232              :       }
     233              :     }
     234            1 :     global_ret = 0;
     235            1 :     break;
     236            0 :   default:
     237            0 :     fprintf (stderr,
     238              :              "Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
     239              :              auth.wire_gateway_url,
     240            0 :              reply->http_status,
     241            0 :              TALER_ErrorCode_get_hint (reply->ec));
     242            0 :     if (NULL != reply->response)
     243            0 :       json_dumpf (reply->response,
     244              :                   stderr,
     245              :                   JSON_INDENT (2));
     246            0 :     global_ret = 2;
     247            0 :     break;
     248              :   }
     249            1 :   GNUNET_SCHEDULER_shutdown ();
     250            1 : }
     251              : 
     252              : 
     253              : /**
     254              :  * Ask the bank the list of transactions for the bank account
     255              :  * mentioned in the config section given by the user.
     256              :  */
     257              : static void
     258            1 : execute_credit_history (void)
     259              : {
     260            1 :   if (NULL != subject)
     261              :   {
     262            0 :     fprintf (stderr,
     263              :              "Specifying subject is not supported when inspecting credit history\n");
     264            0 :     GNUNET_SCHEDULER_shutdown ();
     265            0 :     return;
     266              :   }
     267            2 :   chh = TALER_BANK_credit_history (ctx,
     268              :                                    &auth,
     269              :                                    start_row,
     270              :                                    -10,
     271            1 :                                    GNUNET_TIME_UNIT_ZERO,
     272              :                                    &credit_history_cb,
     273              :                                    NULL);
     274            1 :   if (NULL == chh)
     275              :   {
     276            0 :     fprintf (stderr,
     277              :              "Could not request the credit transaction history.\n");
     278            0 :     GNUNET_SCHEDULER_shutdown ();
     279            0 :     return;
     280              :   }
     281              : }
     282              : 
     283              : 
     284              : /**
     285              :  * Function with the debit transaction history.
     286              :  *
     287              :  * @param cls closure
     288              :  * @param reply response details
     289              :  */
     290              : static void
     291            1 : debit_history_cb (void *cls,
     292              :                   const struct TALER_BANK_DebitHistoryResponse *reply)
     293              : {
     294              :   (void) cls;
     295              : 
     296            1 :   dhh = NULL;
     297            1 :   switch (reply->http_status)
     298              :   {
     299            0 :   case 0:
     300            0 :     fprintf (stderr,
     301              :              "Failed to obtain HTTP reply from `%s'\n",
     302              :              auth.wire_gateway_url);
     303            0 :     global_ret = 2;
     304            0 :     break;
     305            0 :   case MHD_HTTP_NO_CONTENT:
     306            0 :     fprintf (stdout,
     307              :              "No transactions.\n");
     308            0 :     global_ret = 0;
     309            0 :     break;
     310            1 :   case MHD_HTTP_OK:
     311            2 :     for (unsigned int i = 0; i<reply->details.ok.details_length; i++)
     312              :     {
     313            1 :       const struct TALER_BANK_DebitDetails *dd =
     314            1 :         &reply->details.ok.details[i];
     315              : 
     316              :       /* If credit/debit accounts were specified, use as a filter */
     317            1 :       if ( (NULL != credit_account.full_payto) &&
     318            0 :            (0 != TALER_full_payto_cmp (credit_account,
     319              :                                        dd->credit_account_uri) ) )
     320            0 :         continue;
     321            1 :       if ( (NULL != debit_account.full_payto) &&
     322            0 :            (0 != TALER_full_payto_cmp (debit_account,
     323              :                                        reply->details.ok.debit_account_uri) ) )
     324            0 :         continue;
     325            1 :       fprintf (stdout,
     326              :                "%llu: %s->%s (%s) over %s at %s\n",
     327            1 :                (unsigned long long) dd->serial_id,
     328            1 :                reply->details.ok.debit_account_uri.full_payto,
     329            1 :                dd->credit_account_uri.full_payto,
     330            1 :                TALER_B2S (&dd->wtid),
     331              :                TALER_amount2s (&dd->amount),
     332              :                GNUNET_TIME_timestamp2s (dd->execution_date));
     333              :     }
     334            1 :     global_ret = 0;
     335            1 :     break;
     336            0 :   default:
     337            0 :     fprintf (stderr,
     338              :              "Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
     339              :              auth.wire_gateway_url,
     340            0 :              reply->http_status,
     341            0 :              TALER_ErrorCode_get_hint (reply->ec));
     342            0 :     if (NULL != reply->response)
     343            0 :       json_dumpf (reply->response,
     344              :                   stderr,
     345              :                   JSON_INDENT (2));
     346            0 :     global_ret = 2;
     347            0 :     break;
     348              :   }
     349            1 :   GNUNET_SCHEDULER_shutdown ();
     350            1 : }
     351              : 
     352              : 
     353              : /**
     354              :  * Ask the bank the list of transactions for the bank account
     355              :  * mentioned in the config section given by the user.
     356              :  */
     357              : static void
     358            1 : execute_debit_history (void)
     359              : {
     360            1 :   if (NULL != subject)
     361              :   {
     362            0 :     fprintf (stderr,
     363              :              "Specifying subject is not supported when inspecting debit history\n");
     364            0 :     GNUNET_SCHEDULER_shutdown ();
     365            0 :     return;
     366              :   }
     367            2 :   dhh = TALER_BANK_debit_history (ctx,
     368              :                                   &auth,
     369              :                                   start_row,
     370              :                                   -10,
     371            1 :                                   GNUNET_TIME_UNIT_ZERO,
     372              :                                   &debit_history_cb,
     373              :                                   NULL);
     374            1 :   if (NULL == dhh)
     375              :   {
     376            0 :     fprintf (stderr,
     377              :              "Could not request the debit transaction history.\n");
     378            0 :     GNUNET_SCHEDULER_shutdown ();
     379            0 :     return;
     380              :   }
     381              : }
     382              : 
     383              : 
     384              : /**
     385              :  * Callback that processes the outcome of a wire transfer
     386              :  * execution.
     387              :  *
     388              :  * @param cls closure
     389              :  * @param tr response details
     390              :  */
     391              : static void
     392            1 : confirmation_cb (void *cls,
     393              :                  const struct TALER_BANK_TransferResponse *tr)
     394              : {
     395              :   (void) cls;
     396            1 :   eh = NULL;
     397            1 :   if (MHD_HTTP_OK != tr->http_status)
     398              :   {
     399            0 :     fprintf (stderr,
     400              :              "The wire transfer didn't execute correctly (%u/%d).\n",
     401            0 :              tr->http_status,
     402            0 :              tr->ec);
     403            0 :     GNUNET_SCHEDULER_shutdown ();
     404            0 :     return;
     405              :   }
     406              : 
     407            1 :   fprintf (stdout,
     408              :            "Wire transfer #%llu executed successfully at %s.\n",
     409            1 :            (unsigned long long) tr->details.ok.row_id,
     410              :            GNUNET_TIME_timestamp2s (tr->details.ok.timestamp));
     411            1 :   global_ret = 0;
     412            1 :   GNUNET_SCHEDULER_shutdown ();
     413              : }
     414              : 
     415              : 
     416              : /**
     417              :  * Ask the bank to execute a wire transfer.
     418              :  */
     419              : static void
     420            1 : execute_wire_transfer (void)
     421              : {
     422              :   struct TALER_WireTransferIdentifierRawP wtid;
     423              :   void *buf;
     424              :   size_t buf_size;
     425              :   char *params;
     426              : 
     427            1 :   if (NULL != debit_account.full_payto)
     428              :   {
     429            0 :     fprintf (stderr,
     430              :              "Invalid option -C specified, conflicts with -D\n");
     431            0 :     GNUNET_SCHEDULER_shutdown ();
     432            0 :     return;
     433              :   }
     434              : 
     435              :   /* See if subject was given as a payto-parameter. */
     436            1 :   if (NULL == subject)
     437            0 :     subject = TALER_payto_get_subject (credit_account);
     438            1 :   if (NULL != subject)
     439              :   {
     440            1 :     if (GNUNET_OK !=
     441            1 :         GNUNET_STRINGS_string_to_data (subject,
     442              :                                        strlen (subject),
     443              :                                        &wtid,
     444              :                                        sizeof (wtid)))
     445              :     {
     446            0 :       fprintf (stderr,
     447              :                "Error: wire transfer subject must be a WTID\n");
     448            0 :       GNUNET_SCHEDULER_shutdown ();
     449            0 :       return;
     450              :     }
     451              :   }
     452              :   else
     453              :   {
     454              :     /* pick one at random */
     455            0 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     456              :                                 &wtid,
     457              :                                 sizeof (wtid));
     458              :   }
     459            1 :   params = strchr (credit_account.full_payto,
     460              :                    (unsigned char) '&');
     461            1 :   if (NULL != params)
     462            0 :     *params = '\0';
     463            1 :   TALER_BANK_prepare_transfer (credit_account,
     464              :                                &amount,
     465              :                                "http://exchange.example.com/",
     466              :                                &wtid,
     467              :                                &buf,
     468              :                                &buf_size);
     469            1 :   eh = TALER_BANK_transfer (ctx,
     470              :                             &auth,
     471              :                             buf,
     472              :                             buf_size,
     473              :                             &confirmation_cb,
     474              :                             NULL);
     475            1 :   GNUNET_free (buf);
     476            1 :   if (NULL == eh)
     477              :   {
     478            0 :     fprintf (stderr,
     479              :              "Could not execute the wire transfer\n");
     480            0 :     GNUNET_SCHEDULER_shutdown ();
     481            0 :     return;
     482              :   }
     483              : }
     484              : 
     485              : 
     486              : /**
     487              :  * Function called with the result of the operation.
     488              :  *
     489              :  * @param cls closure
     490              :  * @param air response details
     491              :  */
     492              : static void
     493            1 : res_cb (void *cls,
     494              :         const struct TALER_BANK_AdminAddIncomingResponse *air)
     495              : {
     496              :   (void) cls;
     497            1 :   op = NULL;
     498            1 :   switch (air->http_status)
     499              :   {
     500            1 :   case MHD_HTTP_OK:
     501            1 :     global_ret = 0;
     502            1 :     fprintf (stdout,
     503              :              "%llu\n",
     504            1 :              (unsigned long long) air->details.ok.serial_id);
     505            1 :     break;
     506            0 :   default:
     507            0 :     fprintf (stderr,
     508              :              "Operation failed with status code %u/%u\n",
     509            0 :              (unsigned int) air->ec,
     510            0 :              air->http_status);
     511            0 :     if (NULL != air->response)
     512            0 :       json_dumpf (air->response,
     513              :                   stderr,
     514              :                   JSON_INDENT (2));
     515            0 :     break;
     516              :   }
     517            1 :   GNUNET_SCHEDULER_shutdown ();
     518            1 : }
     519              : 
     520              : 
     521              : /**
     522              :  * Ask the bank to execute a wire transfer to the exchange.
     523              :  */
     524              : static void
     525            1 : execute_admin_transfer (void)
     526              : {
     527              :   struct TALER_ReservePublicKeyP reserve_pub;
     528              : 
     529            1 :   if (NULL != subject)
     530              :   {
     531            1 :     if (GNUNET_OK !=
     532            1 :         GNUNET_STRINGS_string_to_data (subject,
     533              :                                        strlen (subject),
     534              :                                        &reserve_pub,
     535              :                                        sizeof (reserve_pub)))
     536              :     {
     537            0 :       fprintf (stderr,
     538              :                "Error: wire transfer subject must be a reserve public key\n");
     539            0 :       return;
     540              :     }
     541              :   }
     542              :   else
     543              :   {
     544              :     /* pick one that is kind-of well-formed at random */
     545            0 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     546              :                                 &reserve_pub,
     547              :                                 sizeof (reserve_pub));
     548              :   }
     549            1 :   op = TALER_BANK_admin_add_incoming (ctx,
     550              :                                       &auth,
     551              :                                       &reserve_pub,
     552              :                                       &amount,
     553              :                                       debit_account,
     554              :                                       &res_cb,
     555              :                                       NULL);
     556            1 :   if (NULL == op)
     557              :   {
     558            0 :     fprintf (stderr,
     559              :              "Could not execute the wire transfer to the exchange\n");
     560            0 :     GNUNET_SCHEDULER_shutdown ();
     561            0 :     return;
     562              :   }
     563              : }
     564              : 
     565              : 
     566              : /**
     567              :  * Run the actual main operation requested by the user.
     568              :  */
     569              : static void
     570            4 : execute_tasks (void)
     571              : {
     572            4 :   if (GNUNET_YES == incoming_history)
     573              :   {
     574            1 :     execute_credit_history ();
     575            1 :     return;
     576              :   }
     577            3 :   if (GNUNET_YES == outgoing_history)
     578              :   {
     579            1 :     execute_debit_history ();
     580            1 :     return;
     581              :   }
     582            2 :   if (NULL != credit_account.full_payto)
     583              :   {
     584            1 :     execute_wire_transfer ();
     585            1 :     return;
     586              :   }
     587            1 :   if (NULL != debit_account.full_payto)
     588              :   {
     589            1 :     execute_admin_transfer ();
     590            1 :     return;
     591              :   }
     592              : 
     593            0 :   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     594              :               "No operation specified.\n");
     595            0 :   global_ret = 0;
     596            0 :   GNUNET_SCHEDULER_shutdown ();
     597              : }
     598              : 
     599              : 
     600              : /**
     601              :  * Receives an access token to the bank.
     602              :  *
     603              :  * @param cls closure
     604              :  * @param atr response details
     605              :  */
     606              : static void
     607            0 : access_token_cb (
     608              :   void *cls,
     609              :   const struct TALER_BANK_AccountTokenResponse *atr)
     610              : {
     611              :   (void) cls;
     612            0 :   ath = NULL;
     613            0 :   switch (atr->ec)
     614              :   {
     615            0 :   case TALER_EC_NONE:
     616            0 :     break; /* continued below */
     617            0 :   default:
     618            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     619              :                 "Failed to get access token: %s (%u/%d)\n",
     620              :                 TALER_ErrorCode_get_hint (atr->ec),
     621              :                 atr->http_status,
     622              :                 (int) atr->ec);
     623            0 :     global_ret = EXIT_NOPERMISSION;
     624            0 :     GNUNET_SCHEDULER_shutdown ();
     625            0 :     return;
     626              :   }
     627            0 :   GNUNET_assert (TALER_BANK_AUTH_BASIC == auth.method);
     628            0 :   GNUNET_free (auth.details.basic.username);
     629            0 :   GNUNET_free (auth.details.basic.password);
     630            0 :   auth.method = TALER_BANK_AUTH_BEARER;
     631            0 :   auth.details.bearer.token = GNUNET_strdup (atr->details.ok.access_token);
     632            0 :   execute_tasks ();
     633              : }
     634              : 
     635              : 
     636              : /**
     637              :  * Main function that will be run.
     638              :  *
     639              :  * @param cls closure
     640              :  * @param args remaining command-line arguments
     641              :  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
     642              :  * @param cfg configuration
     643              :  */
     644              : static void
     645            4 : run (void *cls,
     646              :      char *const *args,
     647              :      const char *cfgfile,
     648              :      const struct GNUNET_CONFIGURATION_Handle *cfg)
     649              : {
     650              :   enum TALER_BANK_TokenScope scope;
     651              :   (void) cls;
     652              :   (void) args;
     653              :   (void) cfgfile;
     654              :   (void) cfg;
     655              : 
     656            4 :   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
     657              :                                  NULL);
     658            4 :   ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
     659              :                           &rc);
     660            4 :   GNUNET_assert (NULL != ctx);
     661            4 :   rc = GNUNET_CURL_gnunet_rc_create (ctx);
     662            4 :   if (NULL != account_section)
     663              :   {
     664            0 :     if (0 != strncasecmp ("exchange-accountcredentials-",
     665              :                           account_section,
     666              :                           strlen ("exchange-accountcredentials-")))
     667              :     {
     668            0 :       fprintf (stderr,
     669              :                "Error: invalid section specified, must begin with `%s`\n",
     670              :                "exchange-accountcredentials-");
     671            0 :       GNUNET_SCHEDULER_shutdown ();
     672            0 :       return;
     673              :     }
     674            0 :     if ( (NULL != auth.wire_gateway_url) ||
     675            0 :          (NULL != auth.details.basic.username) ||
     676            0 :          (NULL != auth.details.basic.password) )
     677              :     {
     678            0 :       fprintf (stderr,
     679              :                "Error: Conflicting authentication options provided. Please only use one method.\n");
     680            0 :       GNUNET_SCHEDULER_shutdown ();
     681            0 :       return;
     682              :     }
     683            0 :     if (GNUNET_OK !=
     684            0 :         TALER_BANK_auth_parse_cfg (cfg,
     685              :                                    account_section,
     686              :                                    &auth))
     687              :     {
     688            0 :       fprintf (stderr,
     689              :                "Error: Authentication information not found in configuration section `%s'\n",
     690              :                account_section);
     691            0 :       GNUNET_SCHEDULER_shutdown ();
     692            0 :       return;
     693              :     }
     694              :   }
     695              :   else
     696              :   {
     697            4 :     if ( (NULL != auth.wire_gateway_url) &&
     698            4 :          (NULL != auth.details.basic.username) &&
     699            0 :          (NULL != auth.details.basic.password) )
     700              :     {
     701            0 :       auth.method = TALER_BANK_AUTH_BASIC;
     702              :     }
     703            4 :     else if ( (NULL != auth.wire_gateway_url) &&
     704            4 :               (NULL != auth.details.bearer.token) )
     705              :     {
     706            0 :       auth.method = TALER_BANK_AUTH_BEARER;
     707              :     }
     708              : 
     709            4 :     else if (NULL == auth.wire_gateway_url)
     710              :     {
     711            0 :       fprintf (stderr,
     712              :                "Error: No account specified (use -b or -s options).\n");
     713            0 :       GNUNET_SCHEDULER_shutdown ();
     714            0 :       return;
     715              :     }
     716              :   }
     717            4 :   if ( (NULL == auth.wire_gateway_url) ||
     718            4 :        (0 == strlen (auth.wire_gateway_url)) ||
     719            4 :        (0 != strncasecmp ("http",
     720            4 :                           auth.wire_gateway_url,
     721              :                           strlen ("http"))) )
     722              :   {
     723            0 :     fprintf (stderr,
     724              :              "Error: Invalid wire gateway URL `%s' configured.\n",
     725              :              auth.wire_gateway_url);
     726            0 :     GNUNET_SCHEDULER_shutdown ();
     727            0 :     return;
     728              :   }
     729            4 :   if ( (GNUNET_YES == incoming_history) &&
     730            1 :        (GNUNET_YES == outgoing_history) )
     731              :   {
     732            0 :     fprintf (stderr,
     733              :              "Error: Please specify only -i or -o, but not both.\n");
     734            0 :     GNUNET_SCHEDULER_shutdown ();
     735            0 :     return;
     736              :   }
     737            4 :   if ( (NULL != auth.core_bank_url) &&
     738            0 :        (TALER_BANK_AUTH_BASIC == auth.method) )
     739              :   {
     740            0 :     scope = TALER_BANK_TOKEN_SCOPE_READONLY;
     741            0 :     if (NULL != credit_account.full_payto)
     742            0 :       scope = TALER_BANK_TOKEN_SCOPE_WIREGATEWAY;
     743            0 :     if (NULL != debit_account.full_payto)
     744            0 :       scope = TALER_BANK_TOKEN_SCOPE_READWRITE;
     745            0 :     ath = TALER_BANK_account_token (ctx,
     746              :                                     &auth,
     747            0 :                                     auth.details.basic.username, // FIXME: why? correct?
     748              :                                     scope,
     749              :                                     false, /* refreshable */
     750              :                                     "taler-exchange-wire-gateway-client CLI token",
     751              :                                     GNUNET_TIME_UNIT_MINUTES,
     752              :                                     &access_token_cb,
     753              :                                     NULL);
     754            0 :     if (NULL == ath)
     755              :     {
     756            0 :       GNUNET_break (0);
     757            0 :       GNUNET_SCHEDULER_shutdown ();
     758            0 :       return;
     759              :     }
     760              :   }
     761              :   else
     762              :   {
     763            4 :     if (TALER_BANK_AUTH_BASIC == auth.method)
     764            0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     765              :                   "No CORE_BANK_URL given in `%s' and using basic authentication. Not all taler-wire-gateway implementations allow this.\n",
     766              :                   account_section);
     767            4 :     execute_tasks ();
     768              :   }
     769              : }
     770              : 
     771              : 
     772              : /**
     773              :  * The main function of the taler-exchange-wire-gateway-client
     774              :  *
     775              :  * @param argc number of arguments from the command line
     776              :  * @param argv command line arguments
     777              :  * @return 0 ok, 1 on error
     778              :  */
     779              : int
     780            4 : main (int argc,
     781              :       char *const *argv)
     782              : {
     783            4 :   const struct GNUNET_GETOPT_CommandLineOption options[] = {
     784            4 :     TALER_getopt_get_amount ('a',
     785              :                              "amount",
     786              :                              "VALUE",
     787              :                              "value to transfer",
     788              :                              &amount),
     789            4 :     GNUNET_GETOPT_option_string ('b',
     790              :                                  "bank",
     791              :                                  "URL",
     792              :                                  "Wire gateway URL to use to talk to the bank",
     793              :                                  &auth.wire_gateway_url),
     794            4 :     GNUNET_GETOPT_option_string ('C',
     795              :                                  "credit",
     796              :                                  "ACCOUNT",
     797              :                                  "payto URI of the bank account to credit (when making outgoing transfers)",
     798              :                                  &credit_account.full_payto),
     799            4 :     GNUNET_GETOPT_option_string ('D',
     800              :                                  "debit",
     801              :                                  "PAYTO-URL",
     802              :                                  "payto URI of the bank account to debit (when making incoming transfers)",
     803              :                                  &debit_account.full_payto),
     804            4 :     GNUNET_GETOPT_option_flag ('i',
     805              :                                "credit-history",
     806              :                                "Ask to get a list of 10 incoming transactions.",
     807              :                                &incoming_history),
     808            4 :     GNUNET_GETOPT_option_flag ('o',
     809              :                                "debit-history",
     810              :                                "Ask to get a list of 10 outgoing transactions.",
     811              :                                &outgoing_history),
     812            4 :     GNUNET_GETOPT_option_string ('p',
     813              :                                  "pass",
     814              :                                  "PASSPHRASE",
     815              :                                  "passphrase to use for authentication",
     816              :                                  &auth.details.basic.password),
     817            4 :     GNUNET_GETOPT_option_string ('s',
     818              :                                  "section",
     819              :                                  "ACCOUNT-SECTION",
     820              :                                  "Which config section has the credentials to access the bank. Conflicts with -b -u and -p options.\n",
     821              :                                  &account_section),
     822            4 :     GNUNET_GETOPT_option_string ('S',
     823              :                                  "subject",
     824              :                                  "SUBJECT",
     825              :                                  "specifies the wire transfer subject",
     826              :                                  &subject),
     827            4 :     GNUNET_GETOPT_option_string ('u',
     828              :                                  "user",
     829              :                                  "USERNAME",
     830              :                                  "username to use for authentication",
     831              :                                  &auth.details.basic.username),
     832            4 :     GNUNET_GETOPT_option_ulong ('w',
     833              :                                 "since-when",
     834              :                                 "ROW",
     835              :                                 "When asking the bank for transactions history, this option commands that all the results should have IDs settled after SW.  If not given, then the 10 youngest transactions are returned.",
     836              :                                 &start_row),
     837              :     GNUNET_GETOPT_OPTION_END
     838              :   };
     839              :   enum GNUNET_GenericReturnValue ret;
     840              : 
     841            4 :   global_ret = 1;
     842            4 :   ret = GNUNET_PROGRAM_run (
     843              :     TALER_EXCHANGE_project_data (),
     844              :     argc, argv,
     845              :     "taler-wire-gateway-client",
     846              :     gettext_noop ("Client tool of the Taler Wire Gateway"),
     847              :     options,
     848              :     &run, NULL);
     849            4 :   if (GNUNET_SYSERR == ret)
     850            0 :     return 3;
     851            4 :   if (GNUNET_NO == ret)
     852            0 :     return 0;
     853            4 :   return global_ret;
     854              : }
     855              : 
     856              : 
     857              : /* end taler-wire-gateway-client.c */
        

Generated by: LCOV version 2.0-1