summaryrefslogtreecommitdiff
path: root/src/mhd/mhd_legal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mhd/mhd_legal.c')
-rw-r--r--src/mhd/mhd_legal.c119
1 files changed, 108 insertions, 11 deletions
diff --git a/src/mhd/mhd_legal.c b/src/mhd/mhd_legal.c
index 2ef36957d..8353a6901 100644
--- a/src/mhd/mhd_legal.c
+++ b/src/mhd/mhd_legal.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2019, 2020 Taler Systems SA
+ Copyright (C) 2019, 2020, 2022, 2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -27,6 +27,11 @@
#include "taler_util.h"
#include "taler_mhd_lib.h"
+/**
+ * How long should browsers/proxies cache the "legal" replies?
+ */
+#define MAX_TERMS_CACHING GNUNET_TIME_UNIT_DAYS
+
/**
* Entry in the terms-of-service array.
@@ -121,10 +126,18 @@ mime_matches (const char *accept_pattern,
{
const char *da = strchr (accept_pattern, '/');
const char *dm = strchr (mime, '/');
+ const char *end;
if ( (NULL == da) ||
(NULL == dm) )
return (0 == strcmp ("*", accept_pattern));
+ // FIXME: use TALER_MHD_check_accept() here!
+ /* FIXME: eventually, we might want to parse the "q=$FLOAT"
+ part after the ';' and figure out which one is the
+ best/preferred match instead of returning a boolean... */
+ end = strchr (da, ';');
+ if (NULL == end)
+ end = &da[strlen (da)];
return
( ( (1 == da - accept_pattern) &&
('*' == *accept_pattern) ) ||
@@ -133,8 +146,9 @@ mime_matches (const char *accept_pattern,
mime,
da - accept_pattern)) ) ) &&
( (0 == strcmp (da, "/*")) ||
- (0 == strcasecmp (da,
- dm)) );
+ (0 == strncasecmp (da,
+ dm,
+ end - da)) );
}
@@ -145,9 +159,9 @@ TALER_MHD_xmime_matches (const char *accept_pattern,
char *ap = GNUNET_strdup (accept_pattern);
char *sptr;
- for (const char *tok = strtok_r (ap, ";", &sptr);
+ for (const char *tok = strtok_r (ap, ",", &sptr);
NULL != tok;
- tok = strtok_r (NULL, ";", &sptr))
+ tok = strtok_r (NULL, ",", &sptr))
{
if (mime_matches (tok,
mime))
@@ -167,7 +181,25 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
{
struct MHD_Response *resp;
struct Terms *t;
-
+ struct GNUNET_TIME_Absolute a;
+ struct GNUNET_TIME_Timestamp m;
+ char dat[128];
+ char *langs;
+
+ a = GNUNET_TIME_relative_to_absolute (MAX_TERMS_CACHING);
+ m = GNUNET_TIME_absolute_to_timestamp (a);
+ /* Round up to next full day to ensure the expiration
+ time does not become a fingerprint! */
+ a = GNUNET_TIME_absolute_round_down (a,
+ MAX_TERMS_CACHING);
+ a = GNUNET_TIME_absolute_add (a,
+ MAX_TERMS_CACHING);
+ TALER_MHD_get_date_string (m.abs_time,
+ dat);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Setting '%s' header to '%s'\n",
+ MHD_HTTP_HEADER_EXPIRES,
+ dat);
if (NULL != legal)
{
const char *etag;
@@ -186,6 +218,15 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
NULL,
MHD_RESPMEM_PERSISTENT);
TALER_MHD_add_global_headers (resp);
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_EXPIRES,
+ dat));
+
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_ETAG,
+ legal->terms_etag));
ret = MHD_queue_response (conn,
MHD_HTTP_NOT_MODIFIED,
resp);
@@ -196,6 +237,7 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
}
t = NULL;
+ langs = NULL;
if (NULL != legal)
{
const char *mime;
@@ -205,7 +247,7 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_ACCEPT);
if (NULL == mime)
- mime = "text/html";
+ mime = "text/plain";
lang = MHD_lookup_connection_value (conn,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_ACCEPT_LANGUAGE);
@@ -221,6 +263,21 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
(TALER_MHD_xmime_matches (mime,
p->mime_type)) )
{
+ if (NULL == langs)
+ {
+ langs = GNUNET_strdup (p->language);
+ }
+ else if (NULL == strstr (langs,
+ p->language))
+ {
+ char *tmp = langs;
+
+ GNUNET_asprintf (&langs,
+ "%s,%s",
+ tmp,
+ p->language);
+ GNUNET_free (tmp);
+ }
if ( (NULL == t) ||
(! TALER_MHD_xmime_matches (mime,
t->mime_type)) ||
@@ -278,6 +335,30 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
MHD_RESPMEM_PERSISTENT);
}
TALER_MHD_add_global_headers (resp);
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_EXPIRES,
+ dat));
+ if (NULL != langs)
+ {
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ "Avail-Languages",
+ langs));
+ GNUNET_free (langs);
+ }
+ /* Set cache control headers: our response varies depending on these headers */
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_VARY,
+ MHD_HTTP_HEADER_ACCEPT_LANGUAGE ","
+ MHD_HTTP_HEADER_ACCEPT ","
+ MHD_HTTP_HEADER_ACCEPT_ENCODING));
+ /* Information is always public, revalidate after 10 days */
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_CACHE_CONTROL,
+ "public,max-age=864000"));
if (NULL != legal)
GNUNET_break (MHD_YES ==
MHD_add_response_header (resp,
@@ -287,6 +368,10 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
MHD_add_response_header (resp,
MHD_HTTP_HEADER_CONTENT_TYPE,
t->mime_type));
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (resp,
+ MHD_HTTP_HEADER_CONTENT_LANGUAGE,
+ t->language));
{
MHD_RESULT ret;
@@ -320,9 +405,10 @@ load_terms (struct TALER_MHD_Legal *legal,
const char *mime;
unsigned int priority;
} mm[] = {
+ { .ext = ".txt", .mime = "text/plain", .priority = 150 },
{ .ext = ".html", .mime = "text/html", .priority = 100 },
{ .ext = ".htm", .mime = "text/html", .priority = 99 },
- { .ext = ".txt", .mime = "text/plain", .priority = 50 },
+ { .ext = ".md", .mime = "text/markdown", .priority = 50 },
{ .ext = ".pdf", .mime = "application/pdf", .priority = 25 },
{ .ext = ".jpg", .mime = "image/jpeg" },
{ .ext = ".jpeg", .mime = "image/jpeg" },
@@ -350,7 +436,7 @@ load_terms (struct TALER_MHD_Legal *legal,
name,
ext - name - 1)) )
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Filename `%s' does not match Etag `%s' in directory `%s/%s'. Ignoring it.\n",
name,
legal->terms_etag,
@@ -415,6 +501,9 @@ load_terms (struct TALER_MHD_Legal *legal,
GNUNET_free (fn);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading legal information from file `%s'\n",
+ fn);
{
void *buf;
size_t bsize;
@@ -515,7 +604,10 @@ load_language (struct TALER_MHD_Legal *legal,
if (fn[0] == '.')
continue;
- load_terms (legal, path, lang, fn);
+ load_terms (legal,
+ path,
+ lang,
+ fn);
}
GNUNET_break (0 == closedir (d));
GNUNET_free (dname);
@@ -578,7 +670,12 @@ TALER_MHD_legal_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
if (lang[0] == '.')
continue;
- load_language (legal, path, lang);
+ if (0 == strcmp (lang,
+ "locale"))
+ continue;
+ load_language (legal,
+ path,
+ lang);
}
GNUNET_break (0 == closedir (d));
GNUNET_free (path);