gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 19/29: added birthdate parser


From: gnunet
Subject: [taler-exchange] 19/29: added birthdate parser
Date: Mon, 03 Jul 2023 16:23:55 +0200

This is an automated email from the git hooks/post-receive script.

oec pushed a commit to branch master
in repository exchange.

commit 145310e20e1a80d7c3a4a76a27f1e415bea7b3ce
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Tue Jun 27 09:45:50 2023 +0200

    added birthdate parser
---
 src/exchange/taler-exchange-httpd_common_kyc.c | 33 ++++++++++--
 src/include/taler_util.h                       | 28 ++++++++++
 src/util/age_restriction.c                     | 53 +++++++++++++++++++
 src/util/test_age_restriction.c                | 73 ++++++++++++++++++++++++++
 4 files changed, 183 insertions(+), 4 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c 
b/src/exchange/taler-exchange-httpd_common_kyc.c
index b6585ed5..bb3ca479 100644
--- a/src/exchange/taler-exchange-httpd_common_kyc.c
+++ b/src/exchange/taler-exchange-httpd_common_kyc.c
@@ -19,9 +19,12 @@
  * @author Christian Grothoff
  */
 #include "platform.h"
+#include "taler-exchange-httpd.h"
 #include "taler-exchange-httpd_common_kyc.h"
 #include "taler_attributes.h"
+#include "taler_error_codes.h"
 #include "taler_exchangedb_plugin.h"
+#include <gnunet/gnunet_common.h>
 
 struct TEH_KycAmlTrigger
 {
@@ -114,7 +117,7 @@ kyc_aml_finished (void *cls,
   size_t eas;
   void *ea;
   const char *birthdate;
-  unsigned int birthday;
+  unsigned int birthday = 0;
   struct GNUNET_ShortHashCode kyc_prox;
   struct GNUNET_AsyncScopeSave old_scope;
 
@@ -125,9 +128,29 @@ kyc_aml_finished (void *cls,
                                        &kyc_prox);
   birthdate = json_string_value (json_object_get (kat->attributes,
                                                   TALER_ATTRIBUTE_BIRTHDATE));
-  birthday = 0; (void) birthdate;  // FIXME-Oec: calculate birthday here...
-  // Convert 'birthdate' to time after 1970, then compute days.
-  // Then compare against max age-restriction, and if before, set to 0.
+
+  if (TEH_age_restriction_enabled)
+  {
+    enum GNUNET_GenericReturnValue ret;
+
+    ret = TALER_parse_coarse_date (birthdate,
+                                   &TEH_age_restriction_config.mask,
+                                   &birthday);
+
+    if (GNUNET_OK != ret)
+    {
+      GNUNET_break (0);
+      if (NULL != kat->response)
+        MHD_destroy_response (kat->response);
+      kat->http_status = MHD_HTTP_BAD_REQUEST;
+      kat->response = TALER_MHD_make_error (
+        TALER_EC_GENERIC_PARAMETER_MALFORMED,
+        TALER_ATTRIBUTE_BIRTHDATE);
+
+      /* FIXME-Christian: shouldn't we return in the error case? */
+    }
+  }
+
   TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key,
                                        kat->attributes,
                                        &ea,
@@ -159,6 +182,8 @@ kyc_aml_finished (void *cls,
     kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
     kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
                                           "do_insert_kyc_attributes");
+
+    /* FIXME-Christian: shouldn't we return in the error case? */
   }
   /* Finally, return result to main handler */
   kat->cb (kat->cb_cls,
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 1f3a4c70..dc30fca3 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -21,6 +21,7 @@
 #ifndef TALER_UTIL_H
 #define TALER_UTIL_H
 
+#include <gnunet/gnunet_common.h>
 #define __TALER_UTIL_LIB_H_INSIDE__
 
 #include <gnunet/gnunet_util_lib.h>
@@ -510,6 +511,33 @@ char *strchrnul (const char *s, int c);
 
 #endif
 
+/**
+ * @brief Parses a date information into days after 1970-01-01 (or 0)
+ *
+ * The input MUST be of the form
+ *
+ *   1) YYYY-MM-DD, representing a valid date
+ *   2) YYYY-MM-00, representing a valid month in a particular year
+ *   3) YYYY-00-00, representing a valid year.
+ *
+ * In the cases 2) and 3) the out parameter is set to the beginning of the
+ * time, f.e. 1950-00-00 == 1950-01-01 and 1888-03-00 == 1888-03-01
+ *
+ * The output will set to the number of days after 1970-01-01 or 0, if the 
input
+ * represents a date belonging to the largest allowed age group.
+ *
+ * @param in Input string representation of the date
+ * @param mask Age mask
+ * @param[out] out Where to write the result
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+enum GNUNET_GenericReturnValue
+TALER_parse_coarse_date (
+  const char *in,
+  const struct TALER_AgeMask *mask,
+  uint32_t *out);
+
+
 /**
  * @brief Parses a string as a list of age groups.
  *
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index b667fa3a..839ed7cd 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -710,4 +710,57 @@ TALER_age_restriction_from_secret (
 }
 
 
+enum GNUNET_GenericReturnValue
+TALER_parse_coarse_date (
+  const char *in,
+  const struct TALER_AgeMask *mask,
+  uint32_t *out)
+{
+  struct tm date = {0};
+  struct tm limit = {0};
+  time_t seconds;
+
+  if (NULL == in)
+  {
+    /* FIXME[oec]: correct behaviour? */
+    *out = 0;
+    return GNUNET_OK;
+  }
+
+  GNUNET_assert (NULL !=mask);
+  GNUNET_assert (NULL !=out);
+
+  if (NULL == strptime (in, "%Y-%0m-%0d", &date))
+  {
+    if (NULL == strptime (in, "%Y-%0m-00", &date))
+      if (NULL == strptime (in, "%Y-00-00", &date))
+        return GNUNET_SYSERR;
+
+    /* turns out that the day is off by one in the last two cases */
+    date.tm_mday += 1;
+  }
+
+  seconds = mktime (&date);
+  if (-1 == seconds)
+    return GNUNET_SYSERR;
+
+  /* calculate the limit date for the largest age group */
+  localtime_r (&(time_t){time (NULL)}, &limit);
+  limit.tm_year -= TALER_get_lowest_age (mask, 255);
+  GNUNET_assert (-1 != mktime (&limit));
+
+  if ((limit.tm_year < date.tm_year)
+      || ((limit.tm_year == date.tm_year)
+          && (limit.tm_mon < date.tm_mon))
+      || ((limit.tm_year == date.tm_year)
+          && (limit.tm_mon == date.tm_mon)
+          && (limit.tm_mday < date.tm_mday)))
+    *out = seconds / 60 / 60 / 24;
+  else
+    *out = 0;
+
+  return GNUNET_OK;
+}
+
+
 /* end util/age_restriction.c */
diff --git a/src/util/test_age_restriction.c b/src/util/test_age_restriction.c
index e1979314..29e722ac 100644
--- a/src/util/test_age_restriction.c
+++ b/src/util/test_age_restriction.c
@@ -129,6 +129,77 @@ test_groups (void)
 }
 
 
+enum GNUNET_GenericReturnValue
+test_dates (void)
+{
+  struct TALER_AgeMask mask = {
+    .bits = 1 | 1 << 5 | 1 << 9 | 1 << 13 | 1 << 17 | 1 << 21
+  };
+
+  struct
+  {
+    char *date;
+    uint32_t expected;
+    enum GNUNET_GenericReturnValue ret;
+  }
+  test [] = {
+    {.date = "abcd-00-00", .expected = 0, .ret = GNUNET_SYSERR},
+    {.date = "1900-00-01", .expected = 0, .ret = GNUNET_SYSERR},
+    {.date = "19000001",   .expected = 0, .ret = GNUNET_SYSERR},
+    {.date = "2001-33-05", .expected = 0, .ret = GNUNET_SYSERR},
+    {.date = "2001-33-35", .expected = 0, .ret = GNUNET_SYSERR},
+
+    {.date = "1900-00-00", .expected = 0, .ret = GNUNET_OK},
+    {.date = "2001-00-00", .expected = 0, .ret = GNUNET_OK},
+    {.date = "2001-03-00", .expected = 0, .ret = GNUNET_OK},
+    {.date = "2001-03-05", .expected = 0, .ret = GNUNET_OK},
+
+    /* These dates should be far enough for the near future so that
+     * the expected values are correct. Will need adjustment in 2044 :) */
+    {.date = "2023-06-26", .expected = 19533, .ret = GNUNET_OK },
+    {.date = "2023-06-01", .expected = 19508, .ret = GNUNET_OK },
+    {.date = "2023-06-00", .expected = 19508, .ret = GNUNET_OK },
+    {.date = "2023-01-01", .expected = 19357, .ret = GNUNET_OK },
+    {.date = "2023-00-00", .expected = 19357, .ret = GNUNET_OK },
+  };
+
+  for (uint8_t t = 0; t < sizeof(test) / sizeof(test[0]); t++)
+  {
+    uint32_t d;
+    enum GNUNET_GenericReturnValue ret;
+
+    ret = TALER_parse_coarse_date (test[t].date,
+                                   &mask,
+                                   &d);
+    if (ret != test[t].ret)
+    {
+      printf (
+        "dates[%d] for date `%s` expected parser to return: %d, got: %d\n",
+        t, test[t].date, test[t].ret, ret);
+      return GNUNET_SYSERR;
+    }
+
+    if (ret == GNUNET_SYSERR)
+      continue;
+
+    if (d != test[t].expected)
+    {
+      printf (
+        "dates[%d] for date `%s` expected value %d, but got %d\n",
+        t, test[t].date, test[t].expected, d);
+      return GNUNET_SYSERR;
+    }
+
+    printf ("dates[%d] for date `%s` got expected value %d\n",
+            t, test[t].date, d);
+  }
+
+  printf ("done with dates\n");
+
+  return GNUNET_OK;
+}
+
+
 enum GNUNET_GenericReturnValue
 test_lowest (void)
 {
@@ -308,6 +379,8 @@ main (int argc,
     GNUNET_break (0);
     return 3;
   }
+  if (GNUNET_OK != test_dates ())
+    return 4;
   return 0;
 }
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]