Compare commits
6 Commits
ddd0e0af13
...
d3d744a444
Author | SHA1 | Date | |
---|---|---|---|
d3d744a444 | |||
1be14a3416 | |||
2f21fa24e4 | |||
89de1678ef | |||
f8536e8c14 | |||
145310e20e |
@ -30,6 +30,8 @@
|
|||||||
#include "taler_kyclogic_lib.h"
|
#include "taler_kyclogic_lib.h"
|
||||||
#include "taler_templating_lib.h"
|
#include "taler_templating_lib.h"
|
||||||
#include "taler_mhd_lib.h"
|
#include "taler_mhd_lib.h"
|
||||||
|
#include "taler-exchange-httpd_age-withdraw.h"
|
||||||
|
#include "taler-exchange-httpd_age-withdraw_reveal.h"
|
||||||
#include "taler-exchange-httpd_aml-decision.h"
|
#include "taler-exchange-httpd_aml-decision.h"
|
||||||
#include "taler-exchange-httpd_auditors.h"
|
#include "taler-exchange-httpd_auditors.h"
|
||||||
#include "taler-exchange-httpd_batch-deposit.h"
|
#include "taler-exchange-httpd_batch-deposit.h"
|
||||||
@ -571,6 +573,46 @@ handle_get_aml (struct TEH_RequestContext *rc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a "/age-withdraw/$ACH/reveal" POST request. Parses the "ACH"
|
||||||
|
* hash of the commitment from a previous call to
|
||||||
|
* /reserves/$reserve_pub/age-withdraw
|
||||||
|
*
|
||||||
|
* @param rc request context
|
||||||
|
* @param root uploaded JSON data
|
||||||
|
* @param args array of additional options
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
static MHD_RESULT
|
||||||
|
handle_post_age_withdraw (struct TEH_RequestContext *rc,
|
||||||
|
const json_t *root,
|
||||||
|
const char *const args[2])
|
||||||
|
{
|
||||||
|
struct TALER_AgeWithdrawCommitmentHashP ach;
|
||||||
|
|
||||||
|
if (0 != strcmp ("reveal", args[1]))
|
||||||
|
return r404 (rc->connection,
|
||||||
|
args[1]);
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_STRINGS_string_to_data (args[0],
|
||||||
|
strlen (args[0]),
|
||||||
|
&ach,
|
||||||
|
sizeof (ach)))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return TALER_MHD_reply_with_error (rc->connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_GENERIC_RESERVE_PUB_MALFORMED,
|
||||||
|
args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TEH_handler_age_withdraw_reveal (rc,
|
||||||
|
&ach,
|
||||||
|
root);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature of functions that handle operations on reserves.
|
* Signature of functions that handle operations on reserves.
|
||||||
*
|
*
|
||||||
@ -617,6 +659,10 @@ handle_post_reserves (struct TEH_RequestContext *rc,
|
|||||||
.op = "batch-withdraw",
|
.op = "batch-withdraw",
|
||||||
.handler = &TEH_handler_batch_withdraw
|
.handler = &TEH_handler_batch_withdraw
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.op = "age-withdraw",
|
||||||
|
.handler = &TEH_handler_age_withdraw
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.op = "withdraw",
|
.op = "withdraw",
|
||||||
.handler = &TEH_handler_withdraw
|
.handler = &TEH_handler_withdraw
|
||||||
@ -1454,6 +1500,12 @@ handle_mhd_request (void *cls,
|
|||||||
.handler.post = &handle_post_reserves,
|
.handler.post = &handle_post_reserves,
|
||||||
.nargs = 2
|
.nargs = 2
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.url = "age-withdraw",
|
||||||
|
.method = MHD_HTTP_METHOD_POST,
|
||||||
|
.handler.post = &handle_post_age_withdraw,
|
||||||
|
.nargs = 2
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.url = "reserves-attest",
|
.url = "reserves-attest",
|
||||||
.method = MHD_HTTP_METHOD_GET,
|
.method = MHD_HTTP_METHOD_GET,
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
* @brief Handle /age-withdraw/$ACH/reveal requests
|
* @brief Handle /age-withdraw/$ACH/reveal requests
|
||||||
* @author Özgür Kesim
|
* @author Özgür Kesim
|
||||||
*/
|
*/
|
||||||
#ifndef TALER_EXCHANGE_HTTPD_AGE_WITHDRAW_H
|
#ifndef TALER_EXCHANGE_HTTPD_AGE_WITHDRAW_REVEAL_H
|
||||||
#define TALER_EXCHANGE_HTTPD_AGE_WITHDRAW_H
|
#define TALER_EXCHANGE_HTTPD_AGE_WITHDRAW_REVEAL_H
|
||||||
|
|
||||||
#include <microhttpd.h>
|
#include <microhttpd.h>
|
||||||
#include "taler-exchange-httpd.h"
|
#include "taler-exchange-httpd.h"
|
||||||
|
@ -311,7 +311,7 @@ batch_withdraw_transaction (void *cls,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
bool balance_ok = false;
|
bool balance_ok = false;
|
||||||
bool age_ok = false;
|
bool age_ok = false;
|
||||||
uint16_t required_age = 0;
|
uint16_t allowed_maximum_age = 0;
|
||||||
char *kyc_required;
|
char *kyc_required;
|
||||||
struct TALER_PaytoHashP reserve_h_payto;
|
struct TALER_PaytoHashP reserve_h_payto;
|
||||||
|
|
||||||
@ -479,7 +479,7 @@ batch_withdraw_transaction (void *cls,
|
|||||||
&found,
|
&found,
|
||||||
&balance_ok,
|
&balance_ok,
|
||||||
&age_ok,
|
&age_ok,
|
||||||
&required_age,
|
&allowed_maximum_age,
|
||||||
&ruuid);
|
&ruuid);
|
||||||
if (0 > qs)
|
if (0 > qs)
|
||||||
{
|
{
|
||||||
@ -508,7 +508,7 @@ batch_withdraw_transaction (void *cls,
|
|||||||
* of the required age */
|
* of the required age */
|
||||||
uint16_t lowest_age = TALER_get_lowest_age (
|
uint16_t lowest_age = TALER_get_lowest_age (
|
||||||
&TEH_age_restriction_config.mask,
|
&TEH_age_restriction_config.mask,
|
||||||
required_age);
|
allowed_maximum_age);
|
||||||
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
TEH_plugin->rollback (TEH_plugin->cls);
|
||||||
*mhd_ret = TEH_RESPONSE_reply_reserve_age_restriction_required (
|
*mhd_ret = TEH_RESPONSE_reply_reserve_age_restriction_required (
|
||||||
|
@ -19,9 +19,12 @@
|
|||||||
* @author Christian Grothoff
|
* @author Christian Grothoff
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "taler-exchange-httpd.h"
|
||||||
#include "taler-exchange-httpd_common_kyc.h"
|
#include "taler-exchange-httpd_common_kyc.h"
|
||||||
#include "taler_attributes.h"
|
#include "taler_attributes.h"
|
||||||
|
#include "taler_error_codes.h"
|
||||||
#include "taler_exchangedb_plugin.h"
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
#include <gnunet/gnunet_common.h>
|
||||||
|
|
||||||
struct TEH_KycAmlTrigger
|
struct TEH_KycAmlTrigger
|
||||||
{
|
{
|
||||||
@ -114,7 +117,7 @@ kyc_aml_finished (void *cls,
|
|||||||
size_t eas;
|
size_t eas;
|
||||||
void *ea;
|
void *ea;
|
||||||
const char *birthdate;
|
const char *birthdate;
|
||||||
unsigned int birthday;
|
unsigned int birthday = 0;
|
||||||
struct GNUNET_ShortHashCode kyc_prox;
|
struct GNUNET_ShortHashCode kyc_prox;
|
||||||
struct GNUNET_AsyncScopeSave old_scope;
|
struct GNUNET_AsyncScopeSave old_scope;
|
||||||
|
|
||||||
@ -125,9 +128,29 @@ kyc_aml_finished (void *cls,
|
|||||||
&kyc_prox);
|
&kyc_prox);
|
||||||
birthdate = json_string_value (json_object_get (kat->attributes,
|
birthdate = json_string_value (json_object_get (kat->attributes,
|
||||||
TALER_ATTRIBUTE_BIRTHDATE));
|
TALER_ATTRIBUTE_BIRTHDATE));
|
||||||
birthday = 0; (void) birthdate; // FIXME-Oec: calculate birthday here...
|
|
||||||
// Convert 'birthdate' to time after 1970, then compute days.
|
if (TEH_age_restriction_enabled)
|
||||||
// Then compare against max age-restriction, and if before, set to 0.
|
{
|
||||||
|
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,
|
TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key,
|
||||||
kat->attributes,
|
kat->attributes,
|
||||||
&ea,
|
&ea,
|
||||||
@ -159,6 +182,8 @@ kyc_aml_finished (void *cls,
|
|||||||
kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
|
kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
"do_insert_kyc_attributes");
|
"do_insert_kyc_attributes");
|
||||||
|
|
||||||
|
/* FIXME-Christian: shouldn't we return in the error case? */
|
||||||
}
|
}
|
||||||
/* Finally, return result to main handler */
|
/* Finally, return result to main handler */
|
||||||
kat->cb (kat->cb_cls,
|
kat->cb (kat->cb_cls,
|
||||||
|
@ -31,7 +31,7 @@ BEGIN
|
|||||||
',current_balance_frac INT4 NOT NULL DEFAULT(0)'
|
',current_balance_frac INT4 NOT NULL DEFAULT(0)'
|
||||||
',purses_active INT8 NOT NULL DEFAULT(0)'
|
',purses_active INT8 NOT NULL DEFAULT(0)'
|
||||||
',purses_allowed INT8 NOT NULL DEFAULT(0)'
|
',purses_allowed INT8 NOT NULL DEFAULT(0)'
|
||||||
',birthdate INT4 NOT NULL DEFAULT(0)'
|
',birthday INT4 NOT NULL DEFAULT(0)'
|
||||||
',expiration_date INT8 NOT NULL'
|
',expiration_date INT8 NOT NULL'
|
||||||
',gc_date INT8 NOT NULL'
|
',gc_date INT8 NOT NULL'
|
||||||
') %s ;'
|
') %s ;'
|
||||||
@ -82,7 +82,7 @@ BEGIN
|
|||||||
);
|
);
|
||||||
PERFORM comment_partitioned_column(
|
PERFORM comment_partitioned_column(
|
||||||
'Birthday of the user in days after 1970, or 0 if user is an adult and is not subject to age restrictions'
|
'Birthday of the user in days after 1970, or 0 if user is an adult and is not subject to age restrictions'
|
||||||
,'birthdate'
|
,'birthday'
|
||||||
,table_name
|
,table_name
|
||||||
,partition_suffix
|
,partition_suffix
|
||||||
);
|
);
|
||||||
|
@ -26,7 +26,7 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_withdraw(
|
|||||||
OUT reserve_found BOOLEAN,
|
OUT reserve_found BOOLEAN,
|
||||||
OUT balance_ok BOOLEAN,
|
OUT balance_ok BOOLEAN,
|
||||||
OUT age_ok BOOLEAN,
|
OUT age_ok BOOLEAN,
|
||||||
OUT allowed_maximum_age INT4, -- in years
|
OUT allowed_maximum_age INT2, -- in years
|
||||||
OUT ruuid INT8)
|
OUT ruuid INT8)
|
||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
@ -74,7 +74,7 @@ END IF;
|
|||||||
-- Check if age requirements are present
|
-- Check if age requirements are present
|
||||||
IF ((NOT do_age_check) OR (reserve_birthday = 0))
|
IF ((NOT do_age_check) OR (reserve_birthday = 0))
|
||||||
THEN
|
THEN
|
||||||
age_ok = OK;
|
age_ok = TRUE;
|
||||||
allowed_maximum_age = -1;
|
allowed_maximum_age = -1;
|
||||||
ELSE
|
ELSE
|
||||||
-- Age requirements are formally not met: The exchange is setup to support
|
-- Age requirements are formally not met: The exchange is setup to support
|
||||||
|
@ -45,9 +45,9 @@ TEH_PG_do_batch_withdraw (
|
|||||||
struct GNUNET_PQ_QueryParam params[] = {
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
TALER_PQ_query_param_amount (amount),
|
TALER_PQ_query_param_amount (amount),
|
||||||
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
|
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
|
||||||
GNUNET_PQ_query_param_bool (do_age_check),
|
|
||||||
GNUNET_PQ_query_param_timestamp (&now),
|
GNUNET_PQ_query_param_timestamp (&now),
|
||||||
GNUNET_PQ_query_param_timestamp (&gc),
|
GNUNET_PQ_query_param_timestamp (&gc),
|
||||||
|
GNUNET_PQ_query_param_bool (do_age_check),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
@ -77,10 +77,10 @@ TEH_PG_do_batch_withdraw (
|
|||||||
" reserve_found"
|
" reserve_found"
|
||||||
",balance_ok"
|
",balance_ok"
|
||||||
",age_ok"
|
",age_ok"
|
||||||
",required_age"
|
",allowed_maximum_age"
|
||||||
",ruuid"
|
",ruuid"
|
||||||
" FROM exchange_do_batch_withdraw"
|
" FROM exchange_do_batch_withdraw"
|
||||||
" ($1,$2,$3,$4,$5);");
|
" ($1,$2,$3,$4,$5,$6);");
|
||||||
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||||
"call_batch_withdraw",
|
"call_batch_withdraw",
|
||||||
params,
|
params,
|
||||||
|
@ -2243,15 +2243,26 @@ TALER_TESTING_cmd_proof_kyc_oauth2 (
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a fake OAuth 2.0 service on @a port for testing
|
* Starts a fake OAuth 2.0 service on @a port for testing
|
||||||
* KYC processes.
|
* KYC processes which also provides a @a birthdate in a response
|
||||||
*
|
*
|
||||||
* @param label command label
|
* @param label command label
|
||||||
* @param port the TCP port to listen on
|
* @param port the TCP port to listen on
|
||||||
*/
|
*/
|
||||||
struct TALER_TESTING_Command
|
struct TALER_TESTING_Command
|
||||||
TALER_TESTING_cmd_oauth (const char *label,
|
TALER_TESTING_cmd_oauth_with_birthdate (const char *label,
|
||||||
|
const char *birthdate,
|
||||||
uint16_t port);
|
uint16_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a fake OAuth 2.0 service on @a port for testing
|
||||||
|
* KYC processes.
|
||||||
|
*
|
||||||
|
* @param label command label
|
||||||
|
* @param port the TCP port to listen on
|
||||||
|
*/
|
||||||
|
#define TALER_TESTING_cmd_oauth(label, port) \
|
||||||
|
TALER_TESTING_cmd_oauth_with_birthdate ((label), NULL, (port))
|
||||||
|
|
||||||
|
|
||||||
/* ****************** P2P payment commands ****************** */
|
/* ****************** P2P payment commands ****************** */
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#ifndef TALER_UTIL_H
|
#ifndef TALER_UTIL_H
|
||||||
#define TALER_UTIL_H
|
#define TALER_UTIL_H
|
||||||
|
|
||||||
|
#include <gnunet/gnunet_common.h>
|
||||||
#define __TALER_UTIL_LIB_H_INSIDE__
|
#define __TALER_UTIL_LIB_H_INSIDE__
|
||||||
|
|
||||||
#include <gnunet/gnunet_util_lib.h>
|
#include <gnunet/gnunet_util_lib.h>
|
||||||
@ -510,6 +511,33 @@ char *strchrnul (const char *s, int c);
|
|||||||
|
|
||||||
#endif
|
#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.
|
* @brief Parses a string as a list of age groups.
|
||||||
*
|
*
|
||||||
|
@ -39,6 +39,11 @@ struct OAuthState
|
|||||||
*/
|
*/
|
||||||
struct MHD_Daemon *mhd;
|
struct MHD_Daemon *mhd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Birthdate that the oauth server should return in a response, may be NULL
|
||||||
|
*/
|
||||||
|
const char *birthdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Port to listen on.
|
* Port to listen on.
|
||||||
*/
|
*/
|
||||||
@ -172,28 +177,33 @@ handler_cb (void *cls,
|
|||||||
void **con_cls)
|
void **con_cls)
|
||||||
{
|
{
|
||||||
struct RequestCtx *rc = *con_cls;
|
struct RequestCtx *rc = *con_cls;
|
||||||
|
struct OAuthState *oas = cls;
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
json_t *body;
|
json_t *body;
|
||||||
|
|
||||||
(void) cls;
|
|
||||||
(void) version;
|
(void) version;
|
||||||
if (0 == strcasecmp (method,
|
if (0 == strcasecmp (method,
|
||||||
MHD_HTTP_METHOD_GET))
|
MHD_HTTP_METHOD_GET))
|
||||||
{
|
{
|
||||||
body = GNUNET_JSON_PACK (
|
json_t *data =
|
||||||
GNUNET_JSON_pack_string (
|
|
||||||
"status",
|
|
||||||
"success"),
|
|
||||||
GNUNET_JSON_pack_object_steal (
|
|
||||||
"data",
|
|
||||||
GNUNET_JSON_PACK (
|
GNUNET_JSON_PACK (
|
||||||
GNUNET_JSON_pack_string ("id",
|
GNUNET_JSON_pack_string ("id",
|
||||||
"XXXID12345678"),
|
"XXXID12345678"),
|
||||||
GNUNET_JSON_pack_string ("first_name",
|
GNUNET_JSON_pack_string ("first_name",
|
||||||
"Bob"),
|
"Bob"),
|
||||||
GNUNET_JSON_pack_string ("last_name",
|
GNUNET_JSON_pack_string ("last_name",
|
||||||
"Builder")
|
"Builder"));
|
||||||
)));
|
if (NULL != oas->birthdate)
|
||||||
|
json_object_set_new (data,
|
||||||
|
"birthdate",
|
||||||
|
json_string_nocheck (oas->birthdate));
|
||||||
|
|
||||||
|
body = GNUNET_JSON_PACK (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
"status",
|
||||||
|
"success"),
|
||||||
|
GNUNET_JSON_pack_object_steal (
|
||||||
|
"data", data));
|
||||||
return TALER_MHD_reply_json_steal (connection,
|
return TALER_MHD_reply_json_steal (connection,
|
||||||
body,
|
body,
|
||||||
MHD_HTTP_OK);
|
MHD_HTTP_OK);
|
||||||
@ -368,13 +378,15 @@ oauth_cleanup (void *cls,
|
|||||||
|
|
||||||
|
|
||||||
struct TALER_TESTING_Command
|
struct TALER_TESTING_Command
|
||||||
TALER_TESTING_cmd_oauth (const char *label,
|
TALER_TESTING_cmd_oauth_with_birthdate (const char *label,
|
||||||
|
const char *birthdate,
|
||||||
uint16_t port)
|
uint16_t port)
|
||||||
{
|
{
|
||||||
struct OAuthState *oas;
|
struct OAuthState *oas;
|
||||||
|
|
||||||
oas = GNUNET_new (struct OAuthState);
|
oas = GNUNET_new (struct OAuthState);
|
||||||
oas->port = port;
|
oas->port = port;
|
||||||
|
oas->birthdate = birthdate;
|
||||||
{
|
{
|
||||||
struct TALER_TESTING_Command cmd = {
|
struct TALER_TESTING_Command cmd = {
|
||||||
.cls = oas,
|
.cls = oas,
|
||||||
|
@ -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 */
|
/* end util/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
|
enum GNUNET_GenericReturnValue
|
||||||
test_lowest (void)
|
test_lowest (void)
|
||||||
{
|
{
|
||||||
@ -308,6 +379,8 @@ main (int argc,
|
|||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
if (GNUNET_OK != test_dates ())
|
||||||
|
return 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user