/** Extract a named subcapture value from the request * * @note This is the PCRE variant of the function. * * @param[in] ctx To allocate subcapture buffer in. * @param[out] out Where to write the subcapture string. * @param[in] request to extract. * @param[in] name of subcapture. * @return * - 0 on success. * - -1 on notfound. */ int regex_request_to_sub_named(TALLOC_CTX *ctx, char **out, REQUEST *request, char const *name) { fr_regcapture_t *rc; char const *p; int ret; rc = request_data_reference(request, request, REQUEST_DATA_REGEX); if (!rc) { RDEBUG4("No subcapture data found"); *out = NULL; return 1; } ret = pcre_get_named_substring(rc->preg->compiled, rc->regmatch->subject, (int *)rc->regmatch->match_data, (int)rc->regmatch->used, name, &p); switch (ret) { case PCRE_ERROR_NOMEMORY: MEM(NULL); /* * We can't really fall through, but GCC 7.3 is * too stupid to realise that we can never get * here despite _fr_exit_now being marked as * NEVER_RETURNS. * * If we did anything else, compilers and static * analysis tools would probably complain about * code that could never be executed *sigh*. */ /* FALL-THROUGH */ /* * Not finding a substring is fine */ case PCRE_ERROR_NOSUBSTRING: RDEBUG4("No named capture group \"%s\"", name); *out = NULL; return -1; default: if (ret < 0) { *out = NULL; return -1; } /* * Check libpcre really is using our overloaded * memory allocation and freeing talloc wrappers. */ talloc_set_type(p, char); talloc_steal(ctx, p); RDEBUG4("Found \"%s\": %pV (%zu)", name, fr_box_strvalue_buffer(p), talloc_array_length(p) - 1); memcpy(out, &p, sizeof(*out)); break; } return 0; }
/** Extract a subcapture value from the request * * @note This is the PCRE variant of the function. * * @param[in] ctx To allocate subcapture buffer in. * @param[out] out Where to write the subcapture string. * @param[in] request to extract. * @param[in] num Subcapture index (0 for entire match). * @return * - 0 on success. * - -1 on notfound. */ int regex_request_to_sub(TALLOC_CTX *ctx, char **out, REQUEST *request, uint32_t num) { fr_regcapture_t *rc; char *buff; size_t len; int ret; pcre2_match_data *match_data; rc = request_data_reference(request, request, REQUEST_DATA_REGEX); if (!rc) { RDEBUG4("No subcapture data found"); *out = NULL; return 1; } match_data = talloc_get_type_abort(rc->regmatch->match_data, pcre2_match_data); ret = pcre2_substring_length_bynumber(match_data, num, &len); switch (ret) { case PCRE2_ERROR_NOMEMORY: MEM(NULL); /* * We can't really fall through, but GCC 7.3 is * too stupid to realise that we can never get * here despite _fr_exit_now being marked as * NEVER_RETURNS. * * If we did anything else, compilers and static * analysis tools would probably complain about * code that could never be executed *sigh*. */ /* FALL-THROUGH */ /* * Not finding a substring is fine */ case PCRE2_ERROR_NOSUBSTRING: RDEBUG4("%i/%zu Not found", num + 1, rc->regmatch->used); *out = NULL; return -1; default: if (ret < 0) { *out = NULL; return -1; } MEM(buff = talloc_array(ctx, char, ++len)); /* +1 for \0, it'll get reset by pcre2_substring */ pcre2_substring_copy_bynumber(match_data, num, (PCRE2_UCHAR *)buff, &len); /* can't error */ RDEBUG4("%i/%zu Found: %pV (%zu)", num + 1, rc->regmatch->used, fr_box_strvalue_buffer(buff), talloc_array_length(buff) - 1); *out = buff; break; } return 0; }
/* * Convert field X to a VP. */ static int csv_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx) { char const *str = uctx; VALUE_PAIR *head = NULL, *vp; fr_cursor_t cursor; fr_dict_attr_t const *da; rad_assert(ctx != NULL); fr_cursor_init(&cursor, &head); /* * FIXME: allow multiple entries. */ if (map->lhs->type == TMPL_TYPE_ATTR) { da = map->lhs->tmpl_da; } else { char *attr; if (tmpl_aexpand(ctx, &attr, request, map->lhs, NULL, NULL) <= 0) { RWDEBUG("Failed expanding string"); return -1; } da = fr_dict_attr_by_name(request->dict, attr); if (!da) { RWDEBUG("No such attribute '%s'", attr); return -1; } talloc_free(attr); } vp = fr_pair_afrom_da(ctx, da); rad_assert(vp); if (fr_pair_value_from_str(vp, str, talloc_array_length(str) - 1, '\0', true) < 0) { RWDEBUG("Failed parsing value \"%pV\" for attribute %s: %s", fr_box_strvalue_buffer(str), map->lhs->tmpl_da->name, fr_strerror()); talloc_free(vp); return -1; } vp->op = map->op; fr_cursor_append(&cursor, vp); *out = head; return 0; }
/** Extract a subcapture value from the request * * @note This is the POSIX variant of the function. * * @param[in] ctx To allocate subcapture buffer in. * @param[out] out Where to write the subcapture string. * @param[in] request to extract. * @param[in] num Subcapture index (0 for entire match). * @return * - 0 on success. * - -1 on notfound. */ int regex_request_to_sub(TALLOC_CTX *ctx, char **out, REQUEST *request, uint32_t num) { fr_regcapture_t *rc; char *buff; char const *start; size_t len; regmatch_t *match_data; rc = request_data_reference(request, request, REQUEST_DATA_REGEX); if (!rc) { RDEBUG4("No subcapture data found"); *out = NULL; return -1; } match_data = rc->regmatch->match_data; /* * Greater than our capture array * * -1 means no value in this capture group. */ if ((num >= rc->regmatch->used) || (match_data[num].rm_eo == -1) || (match_data[num].rm_so == -1)) { RDEBUG4("%i/%zu Not found", num + 1, rc->regmatch->used); *out = NULL; return -1; } /* * Sanity checks on the offsets */ rad_assert(match_data[num].rm_eo <= (regoff_t)talloc_array_length(rc->regmatch->subject)); rad_assert(match_data[num].rm_so <= (regoff_t)talloc_array_length(rc->regmatch->subject)); start = rc->regmatch->subject + match_data[num].rm_so; len = match_data[num].rm_eo - match_data[num].rm_so; MEM(buff = talloc_bstrndup(ctx, start, len)); RDEBUG4("%i/%zu Found: %pV (%zu)", num + 1, rc->regmatch->used, fr_box_strvalue_buffer(buff), len); *out = buff; return 0; }