taler-mdb

GNU Taler Extensions and Integrations
Log | Files | Refs | Submodules | README | LICENSE

commit 0816cc3a2f89e83251c28da99d532880ec29253f
parent d0f3643c3166bd41bcf16c71e1ea4db829704122
Author: Boss Marco <bossm8@students.bfh.ch>
Date:   Mon, 11 Nov 2019 17:54:58 +0100

Merge branch 'refactor' of https://git.taler.net/taler-mdb into refactor

Diffstat:
Mconfigure.ac | 39++++++++++++++++++++++++++++++++++++++-
Msrc/Makefile.am | 1+
Msrc/main.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 158 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -14,7 +14,7 @@ AC_PROG_CC AC_CHECK_LIB([nfc], [nfc_open]) # Checks for header files. -AC_CHECK_HEADERS([stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([stdlib.h string.h unistd.h sys/un.h netinet/in.h netinet/ip.h]) # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL @@ -72,6 +72,38 @@ AC_CHECK_FUNCS([strstr]) LIBS_SAVE=$LIBS +# test for libqrencode +qrencode=0 +QR_LIBS="-lqrencode" +AC_MSG_CHECKING(for libqrencode) +AC_ARG_WITH(qrencode, + [ --with-qrencode=PFX Base of libqrencode installation], + [AC_MSG_RESULT([$with_qrencode]) + AS_CASE([$with_qrencode], + [no],[], + [yes],[ + AC_CHECK_HEADERS(qrencode.h,qrencode=1) + ], + [ + CPPFLAGS="-I$with_qrencode/include $CPPFLAGS" + QR_CFLAGS="-I$with_qrencode/include" + QR_LIBS="-L$with_qrencode/lib -lqrencode" + AC_CHECK_HEADERS(qrencode.h,qrencode=1) + ]) + ], + [AC_MSG_RESULT([--with-qrencode not specified]) + AC_CHECK_HEADERS(qrencode.h,qrencode=1)]) + +AS_IF([test "$qrencode" != 1], +[ +QR_LIBS="" +QR_CFLAGS="" +]) + +AC_SUBST(QR_CFLAGS) +AC_SUBST(QR_LIBS) + + # Check for Taler's libtalermerchant libtalermerchant=0 AC_MSG_CHECKING([for libtalermerchant]) @@ -248,3 +280,8 @@ LIBS=$LIBS_SAVE AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT + +if test "$qrencode" != 1 +then + AC_MSG_WARN([taler-mdb will not include QR support]) +fi diff --git a/src/Makefile.am b/src/Makefile.am @@ -15,6 +15,7 @@ taler_nfc_LDADD = \ -lgnunetutil \ -ljansson \ -lnfc \ + @QR_LIBS@ \ $(XLIB) diff --git a/src/main.c b/src/main.c @@ -22,16 +22,34 @@ along with * @author Boss Marco * @author Christian Grothoff */ +#include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/socket.h> +#if HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_NETINET_IP_H +#include <netinet/ip.h> /* superset of previous */ +#endif +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> #include <termios.h> #include <nfc/nfc.h> -#include <gnunet/platform.h> #include <gnunet/gnunet_util_lib.h> #include <taler/taler_merchant_service.h> +/** + * Disable i18n support. + */ +#define _(s) (s) + #define BACKEND_POLL_TIMEOUT GNUNET_TIME_UNIT_MINUTES #define NFC_FAILURE_RETRY_FREQ GNUNET_TIME_UNIT_SECONDS @@ -131,6 +149,85 @@ static struct PaymentActivity *payment_activity; static struct Product *products; +#if HAVE_QRENCODE_H +#include <qrencode.h> + +/** + * Create the QR code image for our zone. + * + * @param uri what text to show in the QR code + */ +static void +show_qrcode (const char *uri) +{ + QRinput *qri; + QRcode *qrc; + uint8_t *pixels; + unsigned int size; + char *upper; + const unsigned int scale = 3; + const unsigned int n_channels = 3; + + qri = QRinput_new2 (0, QR_ECLEVEL_M); + if (NULL == qri) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRinput_new2"); + return; + } + upper = GNUNET_strdup (uri); + GNUNET_STRINGS_utf8_toupper (uri, upper); + /* first try encoding as uppercase-only alpha-numerical + QR code (much smaller encoding); if that fails, also + try using binary encoding (in case nick contains + special characters). */ + if ((0 != + QRinput_append (qri, + QR_MODE_AN, + strlen (upper), + (unsigned char *) upper)) && + (0 != + QRinput_append (qri, + QR_MODE_8, + strlen (upper), + (unsigned char *) upper))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRinput_append"); + GNUNET_free (upper); + return; + } + GNUNET_free (upper); + qrc = QRcode_encodeInput (qri); + if (NULL == qrc) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRcode_encodeInput"); + QRinput_free (qri); + return; + } + size = qrc->width * scale; + size += 8 - (size % 8); + pixels = GNUNET_malloc (size * size * n_channels); + for (unsigned int x = 0; x < size; x++) + for (unsigned int y = 0; y < size; y++) + { + unsigned int off = + (x * qrc->width / size) + (y * qrc->width / size) * qrc->width; + for (int c = 0; c < n_channels; c++) + pixels[(y * size + x) * n_channels + c] = + (0 == (qrc->data[off] & 1)) ? 0xFF : 0; + } + QRcode_free (qrc); + QRinput_free (qri); + // FIXME: use 'pixels' + GNUNET_free (pixels); +} + + +#endif + + static void SNACK_print_hex_info (const char*message, const uint8_t *hexArray, @@ -243,7 +340,8 @@ wallet_transmit_uri (void *cls) memcpy (message, put_data, sizeof (put_data)); memcpy (&message[sizeof (put_data)], pa->taler_pay_uri, slen); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Sending 'PUT DATA' command to wallet\n"); + "Sending 'PUT DATA' command for `%s' to wallet\n", + pa->taler_pay_uri); if (0 > nfc_initiator_transceive_bytes (pa->pnd, message, sizeof (message), @@ -252,7 +350,8 @@ wallet_transmit_uri (void *cls) NFC_TIMEOUT)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to send command\n"); /* Has this to be an error ? */ + "Failed to send command\n"); + /* Has this to be an error ? */ pa->task = GNUNET_SCHEDULER_add_now (&connect_target, pa); return; @@ -367,7 +466,7 @@ connect_target (void *cls) (pa->nt.nti.nai.szUidLen < UID_LEN_LOWER) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to connect, wrong nfc modulation\n"); + "Failed to connect, wrong NFC modulation\n"); SNACK_print_hex_info ("UID", pa->nt.nti.nai.abtUid, pa->nt.nti.nai.szUidLen); @@ -469,12 +568,17 @@ check_payment_cb (void *cls, { fprintf (stderr, "FIXME: yield product here!\n"); + /* FIXME: hide QR code here! */ } else { - if (GNUNET_YES == pa->wallet_has_uri) + /* Start to check for payment. Note that we do this even before + we talked successfully to the wallet via NFC because we MAY show the + QR code in the future and in that case the payment may happen + anytime even before the NFC communication succeeds. */ + if ( (NULL == pa->cpo) && + (NULL == pa->delay_task) ) { - GNUNET_assert (NULL == pa->delay_task); pa->delay_task = GNUNET_SCHEDULER_add_delayed (MAX_HTTP_RETRY_FREQ, &check_payment_again, pa); @@ -482,7 +586,13 @@ check_payment_cb (void *cls, } if (NULL == pa->taler_pay_uri) { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying to talk to wallet to give it pay URI `%s'\n", + taler_pay_uri); GNUNET_assert (NULL == pa->pnd); +#if HAVE_QRENCODE_H + show_qrcode (taler_pay_uri); +#endif pa->taler_pay_uri = GNUNET_strdup (taler_pay_uri); pa->task = GNUNET_SCHEDULER_add_now (&connect_nfc, pa); @@ -529,6 +639,9 @@ proposal_cb (void *cls, payment_activity = NULL; return; } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Backend successfully created order `%s'\n", + order_id); pa->order_id = GNUNET_strdup (order_id); pa->cpo = TALER_MERCHANT_check_payment (ctx, backendBaseUrl,