From 602f5e3e0824d9c2c9dd1fab29342ecbce3b78da Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 26 Jul 2020 12:44:53 +0200 Subject: first steps towards generating (ugly) HTML replies for /orders/ --- src/backend/taler-merchant-httpd_get-orders-ID.c | 237 +++++++++++++++++++++-- 1 file changed, 218 insertions(+), 19 deletions(-) (limited to 'src/backend/taler-merchant-httpd_get-orders-ID.c') diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c index 21582699..7310483d 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -21,6 +21,7 @@ */ #include "platform.h" #include +#include #include #include #include @@ -220,6 +221,12 @@ struct GetOrderData */ bool refunded; + /** + * Set to true if the client requested HTML, otherwise + * we generate JSON. + */ + bool generate_html; + }; @@ -234,6 +241,77 @@ static struct GetOrderData *god_head; static struct GetOrderData *god_tail; +/** + * Create the QR code image for a URI. + * + * @param uri input string to encode + * @return NULL on error, encoded URI otherwise + */ +static char * +create_qrcode (const char *uri) +{ + QRinput *qri; + QRcode *qrc; + struct GNUNET_Buffer buf = { 0 }; + + qri = QRinput_new2 (0, + QR_ECLEVEL_M); + if (NULL == qri) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRinput_new2"); + return NULL; + } + /* first try encoding as uppercase-only alpha-numerical + QR code (much smaller encoding); if that fails, also + try using binary encoding */ + if ( (0 != + QRinput_append (qri, + QR_MODE_AN, + strlen (uri), + (unsigned char *) uri)) && + (0 != + QRinput_append (qri, + QR_MODE_8, + strlen (uri), + (unsigned char *) uri)) ) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRinput_append"); + QRinput_free (qri); + return NULL; + } + qrc = QRcode_encodeInput (qri); + if (NULL == qrc) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "QRcode_encodeInput"); + QRinput_free (qri); + return NULL; + } + QRinput_free (qri); + /* FIXME-Dold: generate with inline SVG instead of
 here! */
+  GNUNET_buffer_write_str (&buf,
+                           "
\n\n\n\n        ");
+  for (unsigned int y = 0; ywidth; y++)
+  {
+    for (unsigned int x = 0; xwidth; x++)
+    {
+      unsigned int off = x + y * qrc->width;
+      GNUNET_buffer_write_fstr (&buf,
+                                "%s",
+                                (0 != (qrc->data[off] & 1)) ? "██" : "  ");
+    }
+    GNUNET_buffer_write_str (&buf,
+                             "\n        ");
+  }
+  GNUNET_buffer_write_str (&buf,
+                           "\n\n\n\n
"); + QRcode_free (qrc); + return GNUNET_buffer_reap_str (&buf); +} + + /** * Force resuming all suspended order lookups, needed during shutdown. */ @@ -375,13 +453,54 @@ send_pay_request (struct GetOrderData *god, god->order_id, god->session_id, god->hc->instance->settings.id); - ret = TALER_MHD_reply_json_pack (god->sc.con, - MHD_HTTP_OK, - "{s:s, s:s, s:s?}", - "taler_pay_uri", taler_pay_uri, - "order_status", "unpaid", - "already_paid_order_id", - already_paid_order_id); + if (god->generate_html) + { + struct MHD_Response *reply; + char *qr; + char *body; + + qr = create_qrcode (taler_pay_uri); + if (NULL == qr) + { + GNUNET_break (0); + return MHD_NO; + } + GNUNET_asprintf (&body, + "%s", + qr); + GNUNET_free (qr); + reply = MHD_create_response_from_buffer (strlen (body), + body, + MHD_RESPMEM_MUST_COPY); + GNUNET_free (body); + if (NULL == reply) + { + GNUNET_break (0); + return MHD_NO; + } + GNUNET_break (MHD_NO != + MHD_add_response_header (reply, + "Taler", + taler_pay_uri)); + GNUNET_break (MHD_NO != + MHD_add_response_header (reply, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/html")); + ret = MHD_queue_response (god->sc.con, + MHD_HTTP_OK, + reply); + MHD_destroy_response (reply); + } + else + { + ret = TALER_MHD_reply_json_pack (god->sc.con, + MHD_HTTP_OK, + "{s:s, s:s, s:s?}", + "taler_pay_uri", taler_pay_uri, + "order_status", "unpaid", + "already_paid_order_id", + already_paid_order_id); + } GNUNET_free (taler_pay_uri); return ret; } @@ -683,6 +802,44 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, } } + { /* check for 'Accept' header */ + const char *accept; + + accept = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT); + if (NULL != accept) + { + char *a = GNUNET_strdup (accept); + char *saveptr; + + for (char *t = strtok_r (a, ",", &saveptr); + NULL != t; + t = strtok_r (NULL, ",", &saveptr)) + { + char *end; + + /* skip leading whitespace */ + while (isspace ((unsigned char) t[0])) + t++; + /* trim of ';q=' parameter and everything after space */ + end = strchr (t, ';'); + if (NULL != end) + *end = '\0'; + end = strchr (t, ' '); + if (NULL != end) + *end = '\0'; + if (0 == strcasecmp ("text/html", + t)) + { + god->generate_html = true; + break; + } + } + GNUNET_free (a); + } + } /* end check for 'Accept' header */ + { const char *long_poll_timeout_s; @@ -1058,18 +1215,60 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, refund)); } - return TALER_MHD_reply_json_pack ( - connection, - MHD_HTTP_OK, - "{s:s, s:b, s:o, s:o, s:o}", - "order_status", "paid", - "refunded", god->refunded, - "refund_amount", - TALER_JSON_from_amount (&god->refund_amount), - "refunds", - ra, - "merchant_pub", - GNUNET_JSON_from_data_auto (&hc->instance->merchant_pub)); + if (god->generate_html) + { + int ret; + struct MHD_Response *reply; + char *body; + +#if 0 + char *qr; + + qr = create_qrcode (taler_refund_uri); + if (NULL == qr) + { + GNUNET_break (0); + return MHD_NO; + } +#endif + GNUNET_asprintf (&body, + "Paid. Refund: %s", + TALER_amount2s (&god->refund_amount)); + // GNUNET_free (qr); + reply = MHD_create_response_from_buffer (strlen (body), + body, + MHD_RESPMEM_MUST_COPY); + GNUNET_free (body); + if (NULL == reply) + { + GNUNET_break (0); + return MHD_NO; + } + GNUNET_break (MHD_NO != + MHD_add_response_header (reply, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/html")); + ret = MHD_queue_response (god->sc.con, + MHD_HTTP_OK, + reply); + MHD_destroy_response (reply); + return ret; + } + else + { + return TALER_MHD_reply_json_pack ( + connection, + MHD_HTTP_OK, + "{s:s, s:b, s:o, s:o, s:o}", + "order_status", "paid", + "refunded", god->refunded, + "refund_amount", + TALER_JSON_from_amount (&god->refund_amount), + "refunds", + ra, + "merchant_pub", + GNUNET_JSON_from_data_auto (&hc->instance->merchant_pub)); + } } } -- cgit v1.2.3