Compare commits
3 Commits
18394e4afe
...
601c18caba
Author | SHA1 | Date | |
---|---|---|---|
601c18caba | |||
6bfbe260c7 | |||
f94f502a5e |
@ -20,8 +20,10 @@
|
||||
*/
|
||||
#include <platform.h>
|
||||
#include <gnunet/gnunet_json_lib.h>
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_extensions.h"
|
||||
|
||||
/**
|
||||
* Name of the input for the 'sign' and 'show' operation.
|
||||
@ -3314,6 +3316,265 @@ do_setup (char *const *args)
|
||||
}
|
||||
|
||||
|
||||
struct extension
|
||||
{
|
||||
char *name;
|
||||
bool critical;
|
||||
char *version;
|
||||
void *config;
|
||||
|
||||
enum GNUNET_GenericReturnValue (*parse_config)(struct extension *this,
|
||||
const char *section);
|
||||
json_t *(*config_json)(const struct extension *this);
|
||||
};
|
||||
|
||||
static enum GNUNET_GenericReturnValue
|
||||
age_restriction_parse_config (struct extension *this, const char *section)
|
||||
{
|
||||
char *age_groups;
|
||||
struct TALER_AgeMask *mask = GNUNET_malloc (sizeof(struct TALER_AgeMask));
|
||||
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg,
|
||||
section,
|
||||
"AGE_GROUPS",
|
||||
&age_groups))
|
||||
goto ERROR;
|
||||
|
||||
if (GNUNET_OK != TALER_parse_age_group_string (age_groups, mask))
|
||||
goto ERROR;
|
||||
|
||||
this->config = mask;
|
||||
return GNUNET_OK;
|
||||
|
||||
ERROR:
|
||||
GNUNET_free (mask);
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
section,
|
||||
"AGE_GROUPS");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
static json_t *
|
||||
age_restriction_json (const struct extension *this)
|
||||
{
|
||||
|
||||
char *groups = TALER_age_mask_to_string (this->config);
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("critical",
|
||||
this->critical),
|
||||
GNUNET_JSON_pack_string ("version",
|
||||
this->version),
|
||||
GNUNET_JSON_pack_string ("age_groups", groups)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static struct extension extensions[] = {
|
||||
{
|
||||
.name = "age-restriction",
|
||||
.version = "1",
|
||||
.parse_config = &age_restriction_parse_config,
|
||||
.config_json = &age_restriction_json,
|
||||
},
|
||||
/* TODO: add p2p here */
|
||||
{0},
|
||||
};
|
||||
|
||||
|
||||
static const struct extension*
|
||||
get_extension (const char *extension)
|
||||
{
|
||||
for (const struct extension *known = extensions; NULL != known->name; known++)
|
||||
{
|
||||
if (0 == strncasecmp (extension, known->name, strlen (known->name)))
|
||||
return known;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
show_extensions (void *cls, const char *section)
|
||||
{
|
||||
if (0 != global_ret)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == strncasecmp (section,
|
||||
"exchange-extension-",
|
||||
sizeof("exchange-extension-") - 1))
|
||||
{
|
||||
const char *name = section + sizeof("exchange-extension-") - 1;
|
||||
const struct extension *extension = get_extension (name);
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (NULL == extension)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "found extension %s\n", name);
|
||||
{
|
||||
bool enabled = (GNUNET_YES ==
|
||||
GNUNET_CONFIGURATION_get_value_yesno (
|
||||
kcfg, section, "ENABLED"));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"\textension is %s\n",
|
||||
enabled?"ENABLED":"DISABLED");
|
||||
if (! enabled)
|
||||
return;
|
||||
|
||||
ret = extension->parse_config ((struct extension *) extension, section);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
|
||||
name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
json_t *cfg = extension->config_json (extension);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"\tconfig: %s\n",
|
||||
json_dumps (cfg, JSON_INDENT (2)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sign_extensions (void *cls, const char *section)
|
||||
{
|
||||
if (0 != global_ret)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == strncasecmp (section,
|
||||
"exchange-extension-",
|
||||
sizeof("exchange-extension-") - 1))
|
||||
{
|
||||
const char *name = section + sizeof("exchange-extension-") - 1;
|
||||
const struct extension *extension = get_extension (name);
|
||||
|
||||
if (NULL == extension)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (GNUNET_YES ==
|
||||
GNUNET_CONFIGURATION_get_value_yesno (
|
||||
kcfg, section, "ENABLED"))
|
||||
{
|
||||
// TODO
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "TODO signing extension %s\n",
|
||||
name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print the current extensions as configured
|
||||
*/
|
||||
static void
|
||||
do_extensions_show (char *const *args)
|
||||
{
|
||||
|
||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||
&show_extensions,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_extensions_sign (char *const *args)
|
||||
{
|
||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||
&sign_extensions,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_work_extensions (char *const *args)
|
||||
{
|
||||
struct SubCommand cmds[] = {
|
||||
{
|
||||
.name = "show",
|
||||
.help =
|
||||
"show the extensions in the Taler-config and their configured parameters",
|
||||
.cb = &do_extensions_show
|
||||
},
|
||||
{
|
||||
.name = "sign",
|
||||
.help =
|
||||
"sign the configuration of the extensions and publish it with the exchange",
|
||||
.cb = &do_extensions_sign
|
||||
},
|
||||
{
|
||||
.name = NULL,
|
||||
}
|
||||
};
|
||||
if (NULL == args[0])
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"You must provide a subcommand: `show` or `sign`.\n");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
nxt = NULL;
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
if (0 == strcasecmp (cmds[i].name,
|
||||
args[0]))
|
||||
{
|
||||
cmds[i].cb (&args[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != strcasecmp ("help",
|
||||
args[0]))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Unexpected command `%s'\n",
|
||||
args[0]);
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Supported subcommands:\n");
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"- %s: %s\n",
|
||||
cmds[i].name,
|
||||
cmds[i].help);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
work (void *cls)
|
||||
{
|
||||
@ -3390,6 +3651,11 @@ work (void *cls)
|
||||
"upload operation result to exchange (to be performed online!)",
|
||||
.cb = &do_upload
|
||||
},
|
||||
{
|
||||
.name = "extensions",
|
||||
.help = "subcommands for extension handling",
|
||||
.cb = &do_work_extensions
|
||||
},
|
||||
/* list terminator */
|
||||
{
|
||||
.name = NULL,
|
||||
|
@ -28,14 +28,6 @@
|
||||
|
||||
#define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-"
|
||||
|
||||
enum TALER_Extension_ReturnValue
|
||||
{
|
||||
TALER_Extension_OK = 0,
|
||||
TALER_Extension_ERROR_PARSING = 1,
|
||||
TALER_Extension_ERROR_INVALID = 2,
|
||||
TALER_Extension_ERROR_SYS = 3
|
||||
};
|
||||
|
||||
enum TALER_Extension_Type
|
||||
{
|
||||
TALER_Extension_AgeRestriction = 0,
|
||||
@ -109,7 +101,7 @@ TALER_extension_get_by_name (const char *name,
|
||||
* @param[out] mask Mask representation for age restriction.
|
||||
* @return Error, if age groups were invalid, OK otherwise.
|
||||
*/
|
||||
enum TALER_Extension_ReturnValue
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_parse_age_group_string (const char *groups,
|
||||
struct TALER_AgeMask *mask);
|
||||
|
||||
@ -133,7 +125,7 @@ TALER_age_mask_to_string (const struct TALER_AgeMask *mask);
|
||||
* @return Error if extension for age restriction was set but age groups were
|
||||
* invalid, OK otherwise.
|
||||
*/
|
||||
enum TALER_Extension_ReturnValue
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
struct TALER_AgeMask *mask);
|
||||
|
||||
|
@ -831,7 +831,7 @@ decode_keys_json (const json_t *resp_obj,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (TALER_Extension_OK !=
|
||||
if (GNUNET_OK !=
|
||||
TALER_parse_age_group_string (age_groups,
|
||||
&key_data->age_mask))
|
||||
{
|
||||
|
@ -77,9 +77,10 @@ WIRE_GATEWAY_URL = "http://localhost:9081/2/"
|
||||
[bank]
|
||||
HTTP_PORT = 9081
|
||||
|
||||
[exchange-extension-age_restriction]
|
||||
# Enabled extensions
|
||||
[exchange-extension-age-restriction]
|
||||
ENABLED = YES
|
||||
AGE_RESTRICTION = "8:14:16"
|
||||
AGE_GROUPS = "8:10:12:14:16:18:21"
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
|
@ -30,12 +30,12 @@
|
||||
* @return Error if extension for age restriction was set, but age groups were
|
||||
* invalid, OK otherwise.
|
||||
*/
|
||||
enum TALER_Extension_ReturnValue
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
struct TALER_AgeMask *mask)
|
||||
{
|
||||
char *groups;
|
||||
enum TALER_Extension_ReturnValue ret = TALER_Extension_ERROR_SYS;
|
||||
enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
|
||||
|
||||
if ((GNUNET_YES != GNUNET_CONFIGURATION_have_value (cfg,
|
||||
TALER_EXTENSION_SECTION_AGE_RESTRICTION,
|
||||
@ -46,7 +46,7 @@ TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
{
|
||||
/* Age restriction is not enabled */
|
||||
mask->mask = 0;
|
||||
return TALER_Extension_OK;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/* Age restriction is enabled, extract age groups */
|
||||
@ -56,13 +56,13 @@ TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
&groups))
|
||||
{
|
||||
/* FIXME: log error? */
|
||||
return TALER_Extension_ERROR_SYS;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (groups == NULL)
|
||||
{
|
||||
/* No groups defined in config, return default_age_mask */
|
||||
mask->mask = TALER_EXTENSION_DEFAULT_AGE_MASK;
|
||||
return TALER_Extension_OK;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
ret = TALER_parse_age_group_string (groups, mask);
|
||||
@ -79,59 +79,46 @@ TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
* @param[out] mask Bit representation of the age groups.
|
||||
* @return Error if string was invalid, OK otherwise.
|
||||
*/
|
||||
enum TALER_Extension_ReturnValue
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_parse_age_group_string (const char *groups,
|
||||
struct TALER_AgeMask *mask)
|
||||
{
|
||||
enum TALER_Extension_ReturnValue ret = TALER_Extension_ERROR_SYS;
|
||||
char *pos;
|
||||
|
||||
const char *end = groups + strlen (groups);
|
||||
const char *pos = groups;
|
||||
unsigned int prev = 0;
|
||||
unsigned int val;
|
||||
char dummy;
|
||||
unsigned int val = 0;
|
||||
|
||||
while (1)
|
||||
while (pos < end)
|
||||
{
|
||||
pos = strchr (groups, ':');
|
||||
if (NULL != pos)
|
||||
char c = *pos++;
|
||||
if (':' == c)
|
||||
{
|
||||
*pos = 0;
|
||||
}
|
||||
if (prev >= val)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
if (1 != sscanf (groups,
|
||||
"%u%c",
|
||||
&val,
|
||||
&dummy))
|
||||
mask->mask |= 1 << val;
|
||||
prev = val;
|
||||
val = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid input */
|
||||
mask->mask = 0;
|
||||
ret = TALER_Extension_ERROR_PARSING;
|
||||
break;
|
||||
}
|
||||
else if ((0 >= val) || (32 <= val) || (prev >= val))
|
||||
{
|
||||
/* Invalid value */
|
||||
mask->mask = 0;
|
||||
ret = TALER_Extension_ERROR_INVALID;
|
||||
break;
|
||||
}
|
||||
if ('0'>c || '9'<c)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
/* Set the corresponding bit in the mask */
|
||||
mask->mask |= 1 << val;
|
||||
val = 10 * val + c - '0';
|
||||
|
||||
if (NULL == pos)
|
||||
{
|
||||
/* We reached the end. Mark zeroth age-group and exit. */
|
||||
mask->mask |= 1;
|
||||
ret = TALER_Extension_OK;
|
||||
break;
|
||||
if (0>=val || 32<=val)
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
prev = val;
|
||||
*pos = ':';
|
||||
groups = pos + 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (0>=val || 32<=val || prev>=val)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
mask->mask |= 1 << val;
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user