From adf0f4fd36290becd33292d56d819aeaf260d5f6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 3 Aug 2020 11:02:26 +0200 Subject: support i18n with HTML templates --- src/backend/taler-merchant-httpd_get-orders-ID.c | 417 +++-------------------- 1 file changed, 43 insertions(+), 374 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 efe7c2a3..f34b7ec7 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -27,7 +27,8 @@ #include #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_get-orders-ID.h" -#include "../mustach/mustach.h" +#include "taler-merchant-httpd_templating.h" + /** * How often do we retry DB transactions on serialization failures? @@ -245,41 +246,6 @@ struct GetOrderData }; -/** - * Entry in a key-value array we use as the mustach closure. - */ -struct KVC -{ - /** - * A name, used as the key. NULL for the last entry. - */ - const char *name; - - /** - * 0-terminated string value to return for @e name. - */ - char *value; -}; - - -/** - * Entry in a key-value array we use to cache templates. - */ -struct TVE -{ - /** - * A name, used as the key. NULL for the last entry. - */ - const char *name; - - /** - * 0-terminated (!) file data to return for @e name. - */ - char *value; - -}; - - /** * Head of DLL of (suspended) requests. */ @@ -290,218 +256,6 @@ static struct GetOrderData *god_head; */ static struct GetOrderData *god_tail; -/** - * Templated loaded into RAM. - */ -static struct TVE *loaded; - -/** - * Length of the #loaded array. - */ -static unsigned int loaded_length; - - -/** - * Function called by Mustach to enter the section @a name. - * As we do not support sections, we always return 0. - * - * @param cls a `struct KVC[]` array - * @param name section to enter - * @return 0 (do not enter) - */ -static int -m_enter (void *cls, const char *name) -{ - (void) cls; - (void) name; - return 0; -} - - -/** - * Function called by mustach to activate the next item in the - * section. Does nothing, as we do not support sections. - * - * @param cls a `struct KVC[]` array - * @return 0 (no next item to activate) - */ -static int -m_next (void *cls) -{ - (void) cls; - return 0; -} - - -/** - * Function called by Mustach to leave the current section. - * As we do not support sections, we should never be called. - * - * @param cls a `struct KVC[]` array - * @return 0 (not documented by mustach) - */ -static int -m_leave (void *cls) -{ - GNUNET_assert (0); - return 0; -} - - -/** - * Return the value of @a name in @a sbuf. - * - * @param cls a `struct KVC[]` array - * @param name the value to lookup - * @param[out] sbuf where to return the data - * @return mustach-defined status code - */ -static int -m_get (void *cls, - const char *name, - struct mustach_sbuf *sbuf) -{ - struct KVC *kvc = cls; - - for (unsigned int i = 0; NULL != kvc[i].name; i++) - { - if (0 == strcmp (name, - kvc[i].name)) - { - sbuf->value = kvc[i].value; - sbuf->releasecb = NULL; - sbuf->closure = &kvc[i]; - return MUSTACH_OK; - } - } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Template requires value for unexpected name `%s'\n", - name); - return MUSTACH_ERROR_ITEM_NOT_FOUND; -} - - -/** - * Mustach callback at the end. Cleans up the @a cls. - * - * @param cls a `struct KVC[]` array - * @param status status of mustach (ignored) - */ -static void -m_stop (void *cls, - int status) -{ - struct KVC *kvc = cls; - - (void) status; - for (unsigned int i = 0; NULL != kvc[i].name; i++) - GNUNET_free (kvc[i].value); -} - - -/** - * Our 'universal' callbacks for mustach. - */ -static struct mustach_itf itf = { - .enter = &m_enter, - .next = &m_next, - .leave = &m_leave, - .get = &m_get, - .stop = &m_stop -}; - - -/** - * Load Mustach template into memory. Note that we intentionally cache - * failures, that is if we ever failed to load a template, we will never try - * again. - * - * FIXME: support i18n: evaluate Language: header from the browser! - * - * @param name name of the template file to load - * (MUST be a 'static' string in memory!) - * @return NULL on error, otherwise the template - */ -static const char * -load_template (const char *name) -{ - char *fn; - char *map; - int fd; - struct stat sb; - - for (unsigned int i = 0; iclaim_token); if (god->generate_html) { - struct MHD_Response *reply; char *qr; - char *body; - size_t body_size; qr = create_qrcode (taler_pay_uri); if (NULL == qr) @@ -753,58 +504,28 @@ send_pay_request (struct GetOrderData *god, { struct KVC kvc[] = { { "taler_pay_uri", - GNUNET_strdup (taler_pay_uri) }, + taler_pay_uri }, { "taler_pay_qrcode_svg", qr }, { "order_summary", - GNUNET_strdup ("FIXME") }, + "FIXME" }, { NULL, NULL } }; - const char *tmpl; - int eno; - - tmpl = load_template ("request_payment"); - if (NULL == tmpl) + enum GNUNET_GenericReturnValue res; + + res = TMH_return_from_template (god->sc.con, + MHD_HTTP_PAYMENT_REQUIRED, + "request_payment", + taler_pay_uri, + kvc); + if (GNUNET_SYSERR == res) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load template `%s'\n", - "request_payment"); - return MHD_NO; // FIXME: add nicer error reply... - } - if (0 != - (eno = mustach (tmpl, - &itf, - &kvc, - &body, - &body_size))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "mustach failed with error %d\n", - eno); - return MHD_NO; // FIXME: add nicer error reply... + GNUNET_break (0); + ret = MHD_NO; } + ret = MHD_YES; } - - reply = MHD_create_response_from_buffer (body_size, - body, - MHD_RESPMEM_MUST_FREE); - 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_PAYMENT_REQUIRED, - reply); - MHD_destroy_response (reply); + GNUNET_free (qr); } else { @@ -1590,94 +1311,53 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, if (god->generate_html) { - int ret; - struct MHD_Response *reply; - char *body; - size_t body_size; - char *qr; - - qr = create_qrcode ("taler://refund/FIXME"); - if (NULL == qr) - { - GNUNET_break (0); - return MHD_NO; // FIXME: add nicer error reply... - } + enum GNUNET_GenericReturnValue res; - if (god->refunded) + if (god->refunded) // FIXME: don't check for refunded, but for PENDING refund! { - struct KVC kvc[] = { - { "refund_amount", - GNUNET_strdup (TALER_amount2s (&god->refund_amount)) }, - { "refund_uri", - qr }, - { NULL, NULL } - }; - const char *tmpl; + char *qr; - tmpl = load_template ("offer_refund"); - if (NULL == tmpl) + qr = create_qrcode ("taler://refund/FIXME"); + if (NULL == qr) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load template `%s'\n", - "offer_refund"); + GNUNET_break (0); return MHD_NO; // FIXME: add nicer error reply... } - if (0 != - mustach (tmpl, - &itf, - &kvc, - &body, - &body_size)) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "mustach"); - return MHD_NO; // FIXME: add nicer error reply... + struct KVC kvc[] = { + { "refund_amount", + TALER_amount2s (&god->refund_amount) }, + { "refund_uri", + qr }, + { NULL, NULL } + }; + + res = TMH_return_from_template (god->sc.con, + MHD_HTTP_OK, + "offer_refund", + "FIXME: refund-URI here", + kvc); } + GNUNET_free (qr); } else { struct KVC kvc[] = { { NULL, NULL } }; - const char *tmpl; - tmpl = load_template ("show_order_details"); - if (NULL == tmpl) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load template `%s'\n", - "show_order_details"); - return MHD_NO; // FIXME: add nicer error reply... - } - if (0 != - mustach (tmpl, - &itf, - &kvc, - &body, - &body_size)) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "mustach"); - return MHD_NO; // FIXME: add nicer error reply... - } + res = TMH_return_from_template (god->sc.con, + MHD_HTTP_OK, + "show_order_details", + NULL, + kvc); } - reply = MHD_create_response_from_buffer (body_size, - body, - MHD_RESPMEM_MUST_FREE); - if (NULL == reply) + if (GNUNET_SYSERR == res) { 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; + return MHD_YES; } else { @@ -1697,15 +1377,4 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, } -/** - * Nicely shut down. - */ -void __attribute__ ((destructor)) -get_orders_fini () -{ - for (unsigned int i = 0; i