taler-mdb

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

commit f8ab6b7b487e0cb7eac2d91147ddfb52d44ea92d
parent 1344b9e81168da174412b408694978884a101954
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 10 Nov 2019 23:18:29 +0100

prepare logic for generation of QR codes

Diffstat:
Mconfigure.ac | 39++++++++++++++++++++++++++++++++++++++-
Msrc/Makefile.am | 1+
Msrc/main.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 140 insertions(+), 3 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 @@ -151,6 +169,85 @@ 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, @@ -504,7 +601,9 @@ check_payment_cb (void *cls, "Trying to talk to wallet to give it pay URI `%s'\n", taler_pay_uri); GNUNET_assert (NULL == pa->pnd); - /* FIXME: show QR code here! */ +#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);