diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-08-03 11:02:26 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-08-03 11:02:26 +0200 |
commit | adf0f4fd36290becd33292d56d819aeaf260d5f6 (patch) | |
tree | 9f93802a22d7c06dadf2ac0e784e8d8e1fb7a4f6 /src | |
parent | b90d7d27871ca09772a5ff4a5af15928bf3e68cb (diff) | |
download | merchant-adf0f4fd36290becd33292d56d819aeaf260d5f6.tar.gz merchant-adf0f4fd36290becd33292d56d819aeaf260d5f6.tar.bz2 merchant-adf0f4fd36290becd33292d56d819aeaf260d5f6.zip |
support i18n with HTML templates
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/Makefile.am | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_get-orders-ID.c | 417 |
3 files changed, 48 insertions, 375 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index ac2eaafd..925746b3 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -90,7 +90,9 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_post-tips-ID-pickup.c \ taler-merchant-httpd_post-tips-ID-pickup.h \ taler-merchant-httpd_reserves.c \ - taler-merchant-httpd_reserves.h + taler-merchant-httpd_reserves.h \ + taler-merchant-httpd_templating.c \ + taler-merchant-httpd_templating.h taler_merchant_httpd_LDADD = \ $(top_builddir)/src/backenddb/libtalermerchantdb.la \ -ltalerexchange \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 75a4cf4d..92986ab7 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -62,6 +62,7 @@ #include "taler-merchant-httpd_post-orders-ID-pay.h" #include "taler-merchant-httpd_post-tips-ID-pickup.h" #include "taler-merchant-httpd_reserves.h" +#include "taler-merchant-httpd_templating.h" /** * Backlog for listen operation on unix-domain sockets. @@ -1515,6 +1516,7 @@ run (void *cls, "merchant", "FORCE_AUDIT")) TMH_force_audit = GNUNET_YES; + TMH_templating_init (); if (GNUNET_SYSERR == TMH_EXCHANGES_init (config)) { 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 <taler/taler_exchange_service.h> #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? @@ -246,41 +247,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. */ static struct GetOrderData *god_head; @@ -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; i<loaded_length; i++) - { - if (0 == strcmp (loaded[i].name, - name)) - return loaded[i].value; - } - GNUNET_array_grow (loaded, - loaded_length, - loaded_length + 1); - loaded[loaded_length - 1].name = name; - { - char *path; - - path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); - if (NULL == path) - { - GNUNET_break (0); - return NULL; - } - GNUNET_asprintf (&fn, - "%s/merchant/%s.must", - path, - name); - GNUNET_free (path); - } - fd = open (fn, O_RDONLY); - if (-1 == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - fn); - GNUNET_free (fn); - return NULL; - } - if (0 != - fstat (fd, - &sb)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - fn); - GNUNET_free (fn); - GNUNET_break (0 == close (fd)); - return NULL; - } - map = GNUNET_malloc_large (sb.st_size + 1); - if (NULL == map) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "malloc"); - GNUNET_free (fn); - GNUNET_break (0 == close (fd)); - return NULL; - } - if (sb.st_size != - read (fd, - map, - sb.st_size)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "read", - fn); - GNUNET_free (fn); - GNUNET_break (0 == close (fd)); - return NULL; - } - GNUNET_break (0 == close (fd)); - GNUNET_free (fn); - loaded[loaded_length - 1].value = map; - return loaded[loaded_length - 1].value; -} - /** * Create the QR code image for a URI. @@ -739,10 +493,7 @@ send_pay_request (struct GetOrderData *god, &god->claim_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<loaded_length; i++) - GNUNET_free (loaded[i].value); -} - - /* end of taler-merchant-httpd_get-orders-ID.c */ |