};
DIAG_OFF(format-nonliteral)
-static ssize_t date_convert_string(request_t *request, char **out, size_t outlen,
+static xlat_action_t date_convert_string(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
const char *str, rlm_date_t const *inst)
{
- struct tm tminfo;
- time_t date = 0;
+ struct tm tminfo;
+ time_t date = 0;
+ fr_value_box_t *vb;
if (strptime(str, inst->fmt, &tminfo) == NULL) {
REDEBUG("Failed to parse time string \"%s\" as format '%s'", str, inst->fmt);
- return -1;
+ return XLAT_ACTION_FAIL;
}
if (inst->utc) {
}
if (date < 0) {
REDEBUG("Failed converting parsed time into unix time");
- return -1;
+ return XLAT_ACTION_FAIL;
}
- return snprintf(*out, outlen, "%" PRIu64, (uint64_t) date);
+ vb = fr_value_box_alloc(ctx, FR_TYPE_UINT64, NULL, false);
+ vb->vb_uint64 = (uint64_t) date;
+ fr_dcursor_append(out, vb);
+ return XLAT_ACTION_DONE;
}
-static ssize_t date_encode_strftime(char **out, size_t outlen, rlm_date_t const *inst,
+static xlat_action_t date_encode_strftime(TALLOC_CTX *ctx, fr_dcursor_t *out, rlm_date_t const *inst,
request_t *request, time_t date)
{
- struct tm tminfo;
+ struct tm tminfo;
+ char buff[64];
+ fr_value_box_t *vb;
if (inst->utc) {
if (gmtime_r(&date, &tminfo) == NULL) {
REDEBUG("Failed converting time string to gmtime: %s", fr_syserror(errno));
- return -1;
+ return XLAT_ACTION_FAIL;
}
} else {
if (localtime_r(&date, &tminfo) == NULL) {
REDEBUG("Failed converting time string to localtime: %s", fr_syserror(errno));
- return -1;
+ return XLAT_ACTION_FAIL;
}
}
- return strftime(*out, outlen, inst->fmt, &tminfo);
+ if (strftime(buff, sizeof(buff), inst->fmt, &tminfo) == 0) return XLAT_ACTION_FAIL;
+
+ vb = fr_value_box_alloc_null(ctx);
+ fr_value_box_strdup(ctx, vb, NULL, buff, false);
+ fr_dcursor_append(out, vb);
+
+ return XLAT_ACTION_DONE;
}
DIAG_ON(format-nonliteral)
+static int mod_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp, void *uctx)
+{
+ *((void **)xlat_inst) = talloc_get_type_abort(uctx, rlm_date_t);
+ return 0;
+}
+
+static xlat_arg_parser_t const xlat_date_convert_args[] = {
+ { .required = true, .single = true, .type = FR_TYPE_VOID },
+ XLAT_ARG_PARSER_TERMINATOR
+};
+
/** Get or convert time and date
*
* Using the format in the module instance configuration, get
*
* When the request arrived:
@verbatim
-%{date:request}
+%(date:request)
@endverbatim
*
* Now:
@verbatim
-%{date:now}
+%(date:now}
@endverbatim
*
* Examples (Tmp-Integer-0 = 1506101100):
@verbatim
update request {
- &Tmp-String-0 := "%{date:&Tmp-Integer-0}" ("Fri 22 Sep 18:25:00 BST 2017")
- &Tmp-Integer-1 := "%{date:&Tmp-String-0}" (1506101100)
+ &Tmp-String-0 := "%(date:%{Tmp-Integer-0})" ("Fri 22 Sep 18:25:00 BST 2017")
+ &Tmp-Integer-1 := "%(date:%{Tmp-String-0})" (1506101100)
}
@endverbatim
*
* @ingroup xlat_functions
*/
-static ssize_t xlat_date_convert(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
- void const *mod_inst, UNUSED void const *xlat_inst,
- request_t *request, char const *fmt)
+static xlat_action_t xlat_date_convert(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+ void const *xlat_inst, UNUSED void *xlat_thread_inst,
+ fr_value_box_list_t *in)
{
- rlm_date_t const *inst = mod_inst;
- struct tm tminfo;
- fr_pair_t *vp;
+ rlm_date_t const *inst;
+ void *instance;
+ struct tm tminfo;
+ fr_value_box_t *arg = fr_dlist_head(in);
+
+ memcpy(&instance, xlat_inst, sizeof(instance));
+
+ inst = talloc_get_type_abort(instance, rlm_date_t);
memset(&tminfo, 0, sizeof(tminfo));
- if (strcmp(fmt, "request") == 0) {
- return date_encode_strftime(out, outlen, inst, request,
+ if ((arg->type == FR_TYPE_STRING) && (strcmp(arg->vb_strvalue, "request") == 0)) {
+ return date_encode_strftime(ctx, out, inst, request,
fr_time_to_sec(request->packet->timestamp));
}
- if (strcmp(fmt, "now") == 0) {
- return date_encode_strftime(out, outlen, inst, request, fr_time_to_sec(fr_time()));
+ if ((arg->type == FR_TYPE_STRING) && (strcmp(arg->vb_strvalue, "now") == 0)) {
+ return date_encode_strftime(ctx, out, inst, request, fr_time_to_sec(fr_time()));
}
- if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;
-
- switch (vp->vp_type) {
+ switch (arg->type) {
/*
* These are 'to' types, i.e. we'll convert the integers
* to a time structure, and then output it in the specified
* format as a string.
*/
case FR_TYPE_DATE:
- return date_encode_strftime(out, outlen, inst, request, fr_unix_time_to_sec(vp->vp_date));
+ return date_encode_strftime(ctx, out, inst, request, fr_unix_time_to_sec(arg->vb_date));
case FR_TYPE_UINT32:
- return date_encode_strftime(out, outlen, inst, request, (time_t) vp->vp_uint32);
+ return date_encode_strftime(ctx, out, inst, request, (time_t) arg->vb_uint32);
case FR_TYPE_UINT64:
- return date_encode_strftime(out, outlen, inst, request, (time_t) vp->vp_uint64);
+ return date_encode_strftime(ctx, out, inst, request, (time_t) arg->vb_uint64);
/*
* These are 'from' types, i.e. we'll convert the input string
* unix timestamp.
*/
case FR_TYPE_STRING:
- return date_convert_string(request, out, outlen, vp->vp_strvalue, inst);
+ return date_convert_string(ctx, out, request, arg->vb_strvalue, inst);
default:
- REDEBUG("Can't convert type %s into date", fr_table_str_by_value(fr_value_box_type_table, vp->da->type, "<INVALID>"));
+ REDEBUG("Can't convert type %s into date", fr_table_str_by_value(fr_value_box_type_table, arg->type, "<INVALID>"));
}
- return -1;
+ return XLAT_ACTION_FAIL;
}
static int mod_bootstrap(void *instance, CONF_SECTION *conf)
{
- rlm_date_t *inst = instance;
+ rlm_date_t *inst = instance;
+ xlat_t *xlat;
inst->xlat_name = cf_section_name2(conf);
if (!inst->xlat_name) {
inst->xlat_name = cf_section_name1(conf);
}
- xlat_register_legacy(inst, inst->xlat_name, xlat_date_convert, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
+ xlat = xlat_register(inst, inst->xlat_name, xlat_date_convert, false);
+ xlat_func_args(xlat,xlat_date_convert_args);
+ xlat_async_instantiate_set(xlat, mod_xlat_instantiate, rlm_date_t *, NULL, inst);
return 0;
}