len = fr_prints(out, outlen, (char const *) p, vp->vp_length, '"');
break;
+ /*
+ * Note that "%{string:...}" is NOT binary safe!
+ * It is explicitly used to get rid of embedded zeros.
+ */
case PW_TYPE_STRING:
len = strlcpy(out, vp->vp_strvalue, outlen);
break;
if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
+ if (vp->da->type != PW_TYPE_STRING) goto nothing;
+
return radius_xlat(out, outlen, request, vp->vp_strvalue, NULL, NULL);
}
* Check for empty expressions %{}
*/
if ((*q == '}') && (q == p)) {
+ talloc_free(node);
*error = "Empty expression is invalid";
return -(p - fmt);
}
*/
if (node->attr.type == TMPL_TYPE_ATTR_UNDEFINED) {
node->xlat = xlat_find(node->attr.tmpl_unknown_name);
+ if (node->xlat && node->xlat->instance && !node->xlat->internal) {
+ talloc_free(node);
+ *error = "Missing content in expansion";
+ return -(p - fmt) - slen;
+ }
+
if (node->xlat) {
node->type = XLAT_VIRTUAL;
node->fmt = node->attr.tmpl_unknown_name;
*error = "Invalid escape at end of string";
return -(p - fmt);
}
+
p += 2;
+ node->len += 2;
continue;
}
#endif
case XLAT_ALTERNATE:
- DEBUG("%.*sif {", lvl, xlat_tabs);
+ DEBUG("%.*sXLAT-IF {", lvl, xlat_tabs);
xlat_tokenize_debug(node->child, lvl + 1);
DEBUG("%.*s}", lvl, xlat_tabs);
- DEBUG("%.*selse {", lvl, xlat_tabs);
+ DEBUG("%.*sXLAT-ELSE {", lvl, xlat_tabs);
xlat_tokenize_debug(node->alternate, lvl + 1);
DEBUG("%.*s}", lvl, xlat_tabs);
break;
* Don't escape this.
*/
case XLAT_LITERAL:
- XLAT_DEBUG("xlat_aprint LITERAL");
+ XLAT_DEBUG("%.*sxlat_aprint LITERAL", lvl, xlat_spaces);
return talloc_typed_strdup(ctx, node->fmt);
/*
size_t freespace = 256;
struct tm ts;
time_t when;
+ int usec;
- XLAT_DEBUG("xlat_aprint PERCENT");
+ XLAT_DEBUG("%.*sxlat_aprint PERCENT", lvl, xlat_spaces);
str = talloc_array(ctx, char, freespace); /* @todo do better allocation */
p = node->fmt;
when = request->timestamp;
+ usec = 0;
if (request->packet) {
when = request->packet->timestamp.tv_sec;
+ usec = request->packet->timestamp.tv_usec;
}
switch (*p) {
case 'S': /* request timestamp in SQL format*/
if (!localtime_r(&when, &ts)) goto error;
- strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
+ nl = str + strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
+ rad_assert(((str + freespace) - nl) >= 8);
+ snprintf(nl, (str + freespace) - nl, ".%06d", usec);
break;
case 'T': /* request timestamp */
if (!localtime_r(&when, &ts)) goto error;
- strftime(str, freespace, "%Y-%m-%d-%H.%M.%S.000000", &ts);
+ strftime(str, freespace, "%Y-%m-%d-%H.%M.%S", &ts);
+
break;
case 'Y': /* request year */
break;
case XLAT_ATTRIBUTE:
- XLAT_DEBUG("xlat_aprint ATTRIBUTE");
+ XLAT_DEBUG("%.*sxlat_aprint ATTRIBUTE", lvl, xlat_spaces);
/*
* Some attributes are virtual <sigh>
*/
str = xlat_getvp(ctx, request, &node->attr, escape ? false : true, true);
if (str) {
- XLAT_DEBUG("EXPAND attr %s", node->attr.tmpl_da->name);
- XLAT_DEBUG(" ---> %s", str);
+ XLAT_DEBUG("%.*sEXPAND attr %s", lvl, xlat_spaces, node->attr.tmpl_da->name);
+ XLAT_DEBUG("%.*s ---> %s", lvl ,xlat_spaces, str);
}
break;
/*
* Smash \n --> CR.
*
- * The OUTPUT of xlat is a printable string. The INPUT might not be...
+ * The OUTPUT of xlat is a "raw" string. The INPUT is a printable string.
*
* This is really the reverse of fr_prints().
*/
#ifdef HAVE_REGEX
case XLAT_REGEX:
- XLAT_DEBUG("xlat_aprint REGEX");
+ XLAT_DEBUG("%.*sxlat_aprint REGEX", lvl, xlat_spaces);
if (regex_request_to_sub(ctx, &str, request, node->attr.tmpl_num) < 0) return NULL;
break;
#endif
case XLAT_ALTERNATE:
- XLAT_DEBUG("xlat_aprint ALTERNATE");
+ XLAT_DEBUG("%.*sxlat_aprint ALTERNATE", lvl, xlat_spaces);
rad_assert(node->child != NULL);
rad_assert(node->alternate != NULL);
- str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
- if (str) {
- XLAT_DEBUG("ALTERNATE got string: %s", str);
- break;
- }
+ /*
+ * If there are no "next" nodes, call ourselves
+ * recursively, which is fast.
+ *
+ * If there are "next" nodes, call xlat_process()
+ * which does a ton more work.
+ */
+ if (!node->next) {
+ str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
+ if (str) {
+ XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str);
+ } else {
+ str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
+ XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str);
+ }
+ } else {
- XLAT_DEBUG("ALTERNATE going to alternate");
- str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
+ if (xlat_process(&str, request, node->child, escape, escape_ctx) > 0) {
+ XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str);
+ } else {
+ (void) xlat_process(&str, request, node->alternate, escape, escape_ctx);
+ XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str);
+ }
+ }
break;
-
}
/*
* Escape the non-literals we found above.
*/
if (str && escape) {
+ size_t len;
char *escaped;
- escaped = talloc_array(ctx, char, 2048); /* FIXME: do something intelligent */
- escape(request, escaped, 2038, str, escape_ctx);
+ len = talloc_array_length(str) * 3;
+
+ escaped = talloc_array(ctx, char, len);
+ escape(request, escaped, len, str, escape_ctx);
talloc_free(str);
str = escaped;
}
/** Replace %whatever in a string.
*
- * See 'doc/variables.txt' for more information.
+ * See 'doc/configuration/variables.rst' for more information.
*
* @param[out] out Where to write pointer to output buffer.
* @param[in] outlen Size of out.
}
len = strlen(buff);
+
/*
* If out doesn't point to an existing buffer
* copy the pointer to our buffer over.
/** Replace %whatever in a string.
*
- * See 'doc/variables.txt' for more information.
+ * See 'doc/configuration/variables.rst' for more information.
*
* @param[out] out Where to write pointer to output buffer.
* @param[in] outlen Size of out.
ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, xlat_escape_t escape, void *ctx)
{
+ *out = NULL;
return xlat_expand(out, 0, request, fmt, escape, ctx);
}
ssize_t radius_axlat_struct(char **out, REQUEST *request, xlat_exp_t const *xlat, xlat_escape_t escape, void *ctx)
{
+ *out = NULL;
return xlat_expand_struct(out, 0, request, xlat, escape, ctx);
}