diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-08-16 14:06:46 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-08-16 14:06:46 +0200 |
commit | c1d0a7d2e64fd7c6bd041a5259cf212b3aabd414 (patch) | |
tree | 8b5c4d05187336048f13c1e500501f6e6bbda727 /src/backend | |
parent | 19010a2f6d658e78ded8abb02995d9154d22bbf3 (diff) | |
download | merchant-c1d0a7d2e64fd7c6bd041a5259cf212b3aabd414.tar.gz merchant-c1d0a7d2e64fd7c6bd041a5259cf212b3aabd414.tar.bz2 merchant-c1d0a7d2e64fd7c6bd041a5259cf212b3aabd414.zip |
-move templating logic to libtalertemplating of exchange
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/Makefile.am | 6 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 20 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_get-orders-ID.c | 38 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_get-tips-ID.c | 19 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_statics.c | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_templating.c | 452 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_templating.h | 56 |
7 files changed, 43 insertions, 550 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 073fff5e..2bd25251 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -107,12 +107,11 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_spa.c \ taler-merchant-httpd_spa.h \ taler-merchant-httpd_statics.c \ - taler-merchant-httpd_statics.h \ - taler-merchant-httpd_templating.c \ - taler-merchant-httpd_templating.h + taler-merchant-httpd_statics.h taler_merchant_httpd_LDADD = \ $(top_builddir)/src/backenddb/libtalermerchantdb.la \ -ltalerexchange \ + -ltalertemplating \ -ltalermhd \ -ltalerbank \ -ltalerjson \ @@ -123,7 +122,6 @@ taler_merchant_httpd_LDADD = \ -lgnunetcurl \ -lgnunetjson \ -lgnunetutil \ - $(top_builddir)/src/mustach/libmustach.a \ @QR_LIBS@ \ $(XLIB) taler_merchant_httpd_CFLAGS = \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index d5bc19d6..d95dafdc 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -25,6 +25,7 @@ #include <taler/taler_dbevents.h> #include <taler/taler_bank_service.h> #include <taler/taler_mhd_lib.h> +#include <taler/taler_templating_lib.h> #include <taler/taler_exchange_service.h> #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_config.h" @@ -70,7 +71,7 @@ #include "taler-merchant-httpd_reserves.h" #include "taler-merchant-httpd_spa.h" #include "taler-merchant-httpd_statics.h" -#include "taler-merchant-httpd_templating.h" + /** * Fixme: document. @@ -306,6 +307,7 @@ do_shutdown (void *cls) GNUNET_CONTAINER_multihashmap_destroy (TMH_by_id_map); TMH_by_id_map = NULL; } + TALER_TEMPLATING_done (); } @@ -1140,7 +1142,7 @@ url_handler (void *cls, MHD_HTTP_METHOD_HEAD)) method = MHD_HTTP_METHOD_GET; /* MHD will deal with the rest */ - + /* Find out the merchant backend instance for the request. * If there is an instance, remove the instance specification * from the beginning of the request URL. */ @@ -1443,12 +1445,12 @@ url_handler (void *cls, &hc->instance->auth.auth_salt, &hc->instance->auth.auth_hash)); else /* Are the credentials provided OK for CLI override? */ - auth_ok |= ( use_default && - (NULL != TMH_default_auth) && - (NULL != auth) && - (! auth_malformed) && - (0 == strcmp (auth, - TMH_default_auth)) ); + auth_ok |= (use_default && + (NULL != TMH_default_auth) && + (NULL != auth) && + (! auth_malformed) && + (0 == strcmp (auth, + TMH_default_auth)) ); if (! auth_ok) { if (auth_malformed) @@ -1778,7 +1780,7 @@ run (void *cls, "merchant", "FORCE_AUDIT")) TMH_force_audit = GNUNET_YES; - TMH_templating_init (); + TALER_TEMPLATING_init ("merchant"); if (GNUNET_OK != TMH_spa_init ()) { diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c index 53260f67..5d229fc2 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -25,12 +25,12 @@ #include <taler/taler_signatures.h> #include <taler/taler_dbevents.h> #include <taler/taler_json_lib.h> +#include <taler/taler_templating_lib.h> #include <taler/taler_exchange_service.h> #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_get-orders-ID.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_qr.h" -#include "taler-merchant-httpd_templating.h" /** * How often do we retry DB transactions on serialization failures? @@ -691,12 +691,12 @@ send_pay_request (struct GetOrderData *god, qr), GNUNET_JSON_pack_string ("order_summary", get_order_summary (god))); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_PAYMENT_REQUIRED, - "request_payment", - god->hc->instance->settings.id, - taler_pay_uri, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_PAYMENT_REQUIRED, + "request_payment", + god->hc->instance->settings.id, + taler_pay_uri, + context); if (GNUNET_SYSERR == res) { GNUNET_break (0); @@ -1460,12 +1460,12 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, uri), GNUNET_JSON_pack_string ("taler_refund_qrcode_svg", qr)); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_OK, - "offer_refund", - hc->instance->settings.id, - uri, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_OK, + "offer_refund", + hc->instance->settings.id, + uri, + context); json_decref (context); } GNUNET_free (uri); @@ -1484,12 +1484,12 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, &god->refund_amount), TALER_JSON_pack_amount ("refund_taken", &god->refund_taken)); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_OK, - "show_order_details", - hc->instance->settings.id, - NULL, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_OK, + "show_order_details", + hc->instance->settings.id, + NULL, + context); json_decref (context); } if (GNUNET_SYSERR == res) diff --git a/src/backend/taler-merchant-httpd_get-tips-ID.c b/src/backend/taler-merchant-httpd_get-tips-ID.c index f427b168..0486de3e 100644 --- a/src/backend/taler-merchant-httpd_get-tips-ID.c +++ b/src/backend/taler-merchant-httpd_get-tips-ID.c @@ -23,10 +23,11 @@ #include <jansson.h> #include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> +#include <taler/taler_templating_lib.h> #include "taler-merchant-httpd_get-tips-ID.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_qr.h" -#include "taler-merchant-httpd_templating.h" + char * TMH_make_taler_tip_uri (struct MHD_Connection *con, @@ -249,18 +250,18 @@ TMH_get_tips_ID (const struct TMH_RequestHandler *rh, uri), GNUNET_JSON_pack_string ("taler_tip_qrcode_svg", qr)); - ret = TMH_return_from_template (connection, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) + ret = TALER_TEMPLATING_reply (connection, + ( (0 == remaining.value) && + (0 == remaining.fraction) ) ? MHD_HTTP_GONE : MHD_HTTP_OK, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) + ( (0 == remaining.value) && + (0 == remaining.fraction) ) ? "depleted_tip" : "offer_tip", - hc->instance->settings.id, - uri, - context); + hc->instance->settings.id, + uri, + context); json_decref (context); } GNUNET_free (tip_status_url); diff --git a/src/backend/taler-merchant-httpd_statics.c b/src/backend/taler-merchant-httpd_statics.c index 69331087..0cf54713 100644 --- a/src/backend/taler-merchant-httpd_statics.c +++ b/src/backend/taler-merchant-httpd_statics.c @@ -22,8 +22,8 @@ #include <gnunet/gnunet_util_lib.h> #include <taler/taler_util.h> #include <taler/taler_mhd_lib.h> +#include <taler/taler_templating_lib.h> #include "taler-merchant-httpd_statics.h" -#include "../mustach/mustach.h" #include <gnunet/gnunet_mhd_compat.h> diff --git a/src/backend/taler-merchant-httpd_templating.c b/src/backend/taler-merchant-httpd_templating.c deleted file mode 100644 index 9d7766b9..00000000 --- a/src/backend/taler-merchant-httpd_templating.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_templating.c - * @brief logic to load and complete HTML templates - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> -#include <taler/taler_mhd_lib.h> -#include "taler-merchant-httpd_templating.h" -#include "../mustach/mustach.h" -#include "../mustach/mustach-jansson.h" -#include <gnunet/gnunet_mhd_compat.h> - - -/** - * Entry in a key-value array we use to cache templates. - */ -struct TVE -{ - /** - * A name, used as the key. NULL for the last entry. - */ - char *name; - - /** - * Language the template is in. - */ - char *lang; - - /** - * 0-terminated (!) file data to return for @e name and @e lang. - */ - char *value; - -}; - - -/** - * Array of templates loaded into RAM. - */ -static struct TVE *loaded; - -/** - * Length of the #loaded array. - */ -static unsigned int loaded_length; - - -/** - * 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. - * - * @param connection the connection we act upon - * @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 * -lookup_template (struct MHD_Connection *connection, - const char *name) -{ - struct TVE *best = NULL; - const char *lang; - - lang = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT_LANGUAGE); - if (NULL == lang) - lang = "en"; - /* find best match by language */ - for (unsigned int i = 0; i<loaded_length; i++) - { - if (0 != strcmp (loaded[i].name, - name)) - continue; /* does not match by name */ - if ( (NULL == best) || - (TALER_language_matches (lang, - loaded[i].lang) > - TALER_language_matches (lang, - best->lang) ) ) - best = &loaded[i]; - } - if (NULL == best) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No templates found in `%s'\n", - name); - return NULL; - } - return best->value; -} - -/** - * Get the base URL for static resources. - * - * @param con the MHD connection - * @param instance_id the instance ID - * @returns the static files base URL, guaranteed - * to have a trailing slash. - */ -static char * -make_static_url (struct MHD_Connection *con, - const char *instance_id) -{ - const char *host; - const char *forwarded_host; - const char *uri_path; - struct GNUNET_Buffer buf = { 0 }; - - host = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "Host"); - forwarded_host = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "X-Forwarded-Host"); - - uri_path = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "X-Forwarded-Prefix"); - if (NULL != forwarded_host) - host = forwarded_host; - - if (NULL == host) - { - GNUNET_break (0); - return NULL; - } - - GNUNET_assert (NULL != instance_id); - - if (GNUNET_NO == TALER_mhd_is_https (con)) - GNUNET_buffer_write_str (&buf, - "http://"); - else - GNUNET_buffer_write_str (&buf, - "https://"); - GNUNET_buffer_write_str (&buf, - host); - if (NULL != uri_path) - GNUNET_buffer_write_path (&buf, - uri_path); - if (0 != strcmp ("default", - instance_id)) - { - GNUNET_buffer_write_path (&buf, - "instances"); - GNUNET_buffer_write_path (&buf, - instance_id); - } - GNUNET_buffer_write_path (&buf, - "static/"); - return GNUNET_buffer_reap_str (&buf); -} - - - - -/** - * Load a @a template and substitute using @a root, returning - * the result to the @a connection with the given - * @a http_status code. - * - * @param connection the connection we act upon - * @param http_status code to use on success - * @param template basename of the template to load - * @param instance_id instance ID, used to compute static files URL - * @param taler_uri value for "Taler:" header to set, or NULL - * @param root JSON object to pass as the root context - * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, - * #GNUNET_SYSERR on failure (to queue an error) - */ -enum GNUNET_GenericReturnValue -TMH_return_from_template (struct MHD_Connection *connection, - unsigned int http_status, - const char *template, - const char *instance_id, - const char *taler_uri, - json_t *root) -{ - struct MHD_Response *reply; - char *body; - size_t body_size; - - { - const char *tmpl; - int eno; - - tmpl = lookup_template (connection, - template); - if (NULL == tmpl) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load template `%s'\n", - template); - if (MHD_YES != - TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_ACCEPTABLE, - TALER_EC_MERCHANT_GENERIC_FAILED_TO_LOAD_TEMPLATE, - template)) - return GNUNET_SYSERR; - return GNUNET_NO; - } - /* Add default values to the context */ - { - char *static_url = make_static_url (connection, - instance_id); - json_object_set (root, - "static_url", - json_string (static_url)); - GNUNET_free (static_url); - } - if (0 != - (eno = mustach_jansson (tmpl, - root, - &body, - &body_size))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "mustach failed on template `%s' with error %d\n", - template, - eno); - if (MHD_YES != - TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_MERCHANT_GENERIC_FAILED_TO_EXPAND_TEMPLATE, - template)) - return GNUNET_SYSERR; - return GNUNET_NO; - } - } - - /* try to compress reply if client allows it */ - { - bool compressed = false; - - if (MHD_YES == - TALER_MHD_can_compress (connection)) - { - compressed = TALER_MHD_body_compress ((void **) &body, - &body_size); - } - reply = MHD_create_response_from_buffer (body_size, - body, - MHD_RESPMEM_MUST_FREE); - if (NULL == reply) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (compressed) - { - if (MHD_NO == - MHD_add_response_header (reply, - MHD_HTTP_HEADER_CONTENT_ENCODING, - "deflate")) - { - GNUNET_break (0); - MHD_destroy_response (reply); - return GNUNET_SYSERR; - } - } - } - - /* Add standard headers */ - if (NULL != taler_uri) - GNUNET_break (MHD_NO != - MHD_add_response_header (reply, - "Taler", - taler_uri)); - GNUNET_break (MHD_NO != - MHD_add_response_header (reply, - MHD_HTTP_HEADER_CONTENT_TYPE, - "text/html")); - - /* Actually return reply */ - { - MHD_RESULT ret; - - ret = MHD_queue_response (connection, - http_status, - reply); - MHD_destroy_response (reply); - if (MHD_NO == ret) - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Function called with a template's filename. - * - * @param cls closure - * @param filename complete filename (absolute path) - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -static int -load_template (void *cls, - const char *filename) -{ - char *lang; - char *end; - int fd; - struct stat sb; - char *map; - const char *name; - - if ('.' == filename[0]) - return GNUNET_OK; - - name = strrchr (filename, - '/'); - if (NULL == name) - name = filename; - else - name++; - lang = strchr (name, - '.'); - if (NULL == lang) - return GNUNET_OK; /* name must include .$LANG */ - lang++; - end = strchr (lang, - '.'); - if ( (NULL == end) || - (0 != strcmp (end, - ".must")) ) - return GNUNET_OK; /* name must end with '.must' */ - - /* finally open template */ - fd = open (filename, - O_RDONLY); - if (-1 == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - filename); - - return GNUNET_SYSERR; - } - if (0 != - fstat (fd, - &sb)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - filename); - GNUNET_break (0 == close (fd)); - return GNUNET_OK; - } - map = GNUNET_malloc_large (sb.st_size + 1); - if (NULL == map) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "malloc"); - GNUNET_break (0 == close (fd)); - return GNUNET_SYSERR; - } - if (sb.st_size != - read (fd, - map, - sb.st_size)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "read", - filename); - GNUNET_break (0 == close (fd)); - return GNUNET_OK; - } - GNUNET_break (0 == close (fd)); - GNUNET_array_grow (loaded, - loaded_length, - loaded_length + 1); - loaded[loaded_length - 1].name = GNUNET_strndup (name, - (lang - 1) - name); - loaded[loaded_length - 1].lang = GNUNET_strndup (lang, - end - lang); - loaded[loaded_length - 1].value = map; - return GNUNET_OK; -} - - -/** - * Preload templates. - */ -int -TMH_templating_init () -{ - char *dn; - int ret; - - { - char *path; - - path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); - if (NULL == path) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_asprintf (&dn, - "%s/merchant/templates/", - path); - GNUNET_free (path); - } - ret = GNUNET_DISK_directory_scan (dn, - &load_template, - NULL); - GNUNET_free (dn); - if (-1 == ret) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Nicely shut down. - */ -void __attribute__ ((destructor)) -templating_fini () -{ - for (unsigned int i = 0; i<loaded_length; i++) - { - GNUNET_free (loaded[i].name); - GNUNET_free (loaded[i].lang); - GNUNET_free (loaded[i].value); - } - GNUNET_array_grow (loaded, - loaded_length, - 0); -} diff --git a/src/backend/taler-merchant-httpd_templating.h b/src/backend/taler-merchant-httpd_templating.h deleted file mode 100644 index a1c2e05a..00000000 --- a/src/backend/taler-merchant-httpd_templating.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_templating.h - * @brief logic to load and complete HTML templates - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_TEMPLATING_H -#define TALER_MERCHANT_HTTPD_TEMPLATING_H - -#include <microhttpd.h> - - -/** - * Load a @a template and substitute using @a root, returning - * the result to the @a connection with the given - * @a http_status code. - * - * @param connection the connection we act upon - * @param http_status code to use on success - * @param template basename of the template to load - * @param instance_id instance ID, used to compute static files URL - * @param taler_uri value for "Taler:" header to set, or NULL - * @param root JSON object to pass as the root context - * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, - * #GNUNET_SYSERR on failure (to queue an error) - */ -enum GNUNET_GenericReturnValue -TMH_return_from_template (struct MHD_Connection *connection, - unsigned int http_status, - const char *template, - const char *instance_id, - const char *taler_uri, - json_t *root); - -/** - * Preload templates. - */ -int -TMH_templating_init (void); - - -#endif |