#include <freeradius-devel/util/dns.h>
#include <freeradius-devel/util/file.h>
#include <freeradius-devel/util/log.h>
-#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/pair_legacy.h>
#include <freeradius-devel/util/sha1.h>
#include <freeradius-devel/util/syserror.h>
#include <freeradius-devel/util/file.h>
#include <freeradius-devel/util/misc.h>
#include <freeradius-devel/util/perm.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/md5.h>
#define RULES_VERIFY(_cs, _rules) if (cf_tmpl_rules_verify(_cs, _rules) < 0) return NULL
-static ssize_t fr_skip_xlat(char const *start, char const *end);
-
/*
* Expand the variables in an input string.
*
static int cf_file_fill(cf_stack_t *stack);
-/** Skip an xlat expression.
- *
- * This is a simple "peek ahead" parser which tries to not be wrong. It may accept
- * some things which will later parse as invalid (e.g. unknown attributes, etc.)
- * But it also rejects all malformed expressions.
- *
- * It's used as a quick hack because the full parser isn't always available.
- *
- * @param[in] start start of the expression, MUST point to the "%{" or "%("
- * @param[in] end end of the string (or NULL for zero-terminated strings)
- * @return
- * >0 length of the string which was parsed
- * <=0 on error
- */
-static ssize_t fr_skip_xlat(char const *start, char const *end)
-{
- int depth = 1; /* caller skips '{' */
- ssize_t slen;
- char quote, end_quote;
- char const *p = start;
-
- /*
- * At least %{1}
- */
- if (end && ((start + 4) > end)) {
- fr_strerror_const("Invalid expansion");
- return 0;
- }
-
- if ((*p != '%') && (*p != '$')) {
- fr_strerror_const("Unexpected character in expansion");
- return -(p - start);
- }
-
- p++;
- if ((*p != '{') && (*p != '(')) {
- char const *q = p;
-
- /*
- * New xlat syntax: %foo(...)
- */
- while (isalnum((int) *q) || (*q == '.') || (*q == '_') || (*q == '-')) {
- q++;
- }
- if (*q == '(') {
- p = q;
- goto do_quote;
- }
-
- fr_strerror_const("Invalid character after '%'");
- return -(p - start);
- }
-
-do_quote:
- quote = *(p++);
- if (quote == '{') {
- end_quote = '}';
- } else {
- end_quote = ')';
- }
-
- while ((end && (p < end)) || (*p >= ' ')) {
- if (*p == quote) {
- p++;
- depth++;
- continue;
- }
-
- if (*p == end_quote) {
- p++;
- depth--;
- if (!depth) return p - start;
-
- continue;
- }
-
- /*
- * Nested expansion.
- */
- if ((p[0] == '$') || (p[0] == '%')) {
- if (end && (p + 2) >= end) break;
-
- if ((p[1] == '{') || ((p[0] == '$') && (p[1] == '('))) {
- slen = fr_skip_xlat(p, end);
-
- check:
- if (slen <= 0) return -(p - start) + slen;
-
- p += slen;
- continue;
- }
-
- /*
- * Bare $ or %, just leave it alone.
- */
- p++;
- continue;
- }
-
- /*
- * A quoted string.
- */
- if ((*p == '"') || (*p == '\'') || (*p == '`')) {
- slen = fr_skip_string(p, end);
- goto check;
- }
-
- /*
- * @todo - bare '(' is a condition or nested
- * expression. The brackets need to balance
- * here, too.
- */
-
- if (*p != '\\') {
- p++;
- continue;
- }
-
- if (end && ((p + 2) >= end)) break;
-
- /*
- * Escapes here are only one-character escapes.
- */
- if (p[1] < ' ') break;
- p += 2;
- }
-
- /*
- * Unexpected end of xlat
- */
- fr_strerror_const("Unexpected end of expansion");
- return -(p - start);
-}
-
static const bool terminal_end_section[UINT8_MAX + 1] = {
['{'] = true,
};
['}'] = true,
};
-/** Skip a conditional expression.
- *
- * This is a simple "peek ahead" parser which tries to not be wrong. It may accept
- * some things which will later parse as invalid (e.g. unknown attributes, etc.)
- * But it also rejects all malformed expressions.
- *
- * It's used as a quick hack because the full parser isn't always available.
- *
- * @param[in] start start of the condition.
- * @param[in] end end of the string (or NULL for zero-terminated strings)
- * @param[in] terminal terminal character(s)
- * @param[out] eol did the parse error happen at eol?
- * @return
- * >0 length of the string which was parsed. *eol is false.
- * <=0 on error, *eol may be set.
- */
-static ssize_t fr_skip_condition(char const *start, char const *end, bool const terminal[static UINT8_MAX + 1], bool *eol)
-{
- char const *p = start;
- bool was_regex = false;
- int depth = 0;
- ssize_t slen;
-
- if (eol) *eol = false;
-
- /*
- * Keep parsing the condition until we hit EOS or EOL.
- */
- while ((end && (p < end)) || *p) {
- if (isspace((uint8_t) *p)) {
- p++;
- continue;
- }
-
- /*
- * In the configuration files, conditions end with ") {" or just "{"
- */
- if ((depth == 0) && terminal[(uint8_t) *p]) {
- return p - start;
- }
-
- /*
- * "recurse" to get more conditions.
- */
- if (*p == '(') {
- p++;
- depth++;
- was_regex = false;
- continue;
- }
-
- if (*p == ')') {
- if (!depth) {
- fr_strerror_const("Too many ')'");
- return -(p - start);
- }
-
- p++;
- depth--;
- was_regex = false;
- continue;
- }
-
- /*
- * Parse xlats. They cannot span EOL.
- */
- if ((*p == '$') || (*p == '%')) {
- if (end && ((p + 2) >= end)) {
- fr_strerror_const("Expansions cannot extend across end of line");
- return -(p - start);
- }
-
- if ((p[1] == '{') || ((p[0] == '$') && (p[1] == '('))) {
- slen = fr_skip_xlat(p, end);
-
- check:
- if (slen <= 0) return -(p - start) + slen;
-
- p += slen;
- continue;
- }
-
- /*
- * Bare $ or %, just leave it alone.
- */
- p++;
- was_regex = false;
- continue;
- }
-
- /*
- * Parse quoted strings. They cannot span EOL.
- */
- if ((*p == '"') || (*p == '\'') || (*p == '`') || (was_regex && (*p == '/'))) {
- was_regex = false;
-
- slen = fr_skip_string((char const *) p, end);
- goto check;
- }
-
- /*
- * 192.168/16 is a netmask. So we only
- * allow regex after a regex operator.
- *
- * This isn't perfect, but is good enough
- * for most purposes.
- */
- if ((p[0] == '=') || (p[0] == '!')) {
- if (end && ((p + 2) >= end)) {
- fr_strerror_const("Operators cannot extend across end of line");
- return -(p - start);
- }
-
- if (p[1] == '~') {
- was_regex = true;
- p += 2;
- continue;
- }
-
- /*
- * Some other '==' or '!=', just leave it alone.
- */
- p++;
- was_regex = false;
- continue;
- }
-
- /*
- * Any control characters (other than \t) cause an error.
- */
- if (*p < ' ') break;
-
- was_regex = false;
-
- /*
- * Normal characters just get skipped.
- */
- if (*p != '\\') {
- p++;
- continue;
- }
-
- /*
- * Backslashes at EOL are ignored.
- */
- if (end && ((p + 2) >= end)) break;
-
- /*
- * Escapes here are only one-character escapes.
- */
- if (p[1] < ' ') break;
- p += 2;
- }
-
- /*
- * We've fallen off of the end of a string. It may be OK?
- */
- if (eol) *eol = (depth > 0);
-
- if (terminal[(uint8_t) *p]) return p - start;
-
- fr_strerror_const("Unexpected end of condition");
- return -(p - start);
-}
-
static CONF_ITEM *process_if(cf_stack_t *stack)
{
ssize_t slen = 0;
#include <freeradius-devel/server/log.h>
#include <freeradius-devel/util/debug.h>
-#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
/*
* Registration hooks for radmin.
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/util/base16.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/perm.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/base16.h>
-#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/pair_legacy.h>
#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
sem.c \
sha1.c \
size.c \
+ skip.c \
snprintf.c \
socket.c \
stats.c \
# define VERIFY_ALL_TALLOC
#endif
-/** Skip whitespace ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
- *
- * @param[in,out] _p string to skip over.
- */
-#define fr_skip_whitespace(_p) while(isspace((uint8_t)*(_p))) _p++
-
-/** Skip whitespace, stopping at end ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
- *
- * @param[in,out] _p string to skip over.
- * @param[in] _e pointer to end of string.
- */
-#define fr_bskip_whitespace(_p, _e) while((_p < _e) && isspace((uint8_t)*(_p))) _p++
-
-/** Skip everything that's not whitespace ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
- *
- * @param[in,out] _p string to skip over.
- */
-#define fr_skip_not_whitespace(_p) while(*_p && !isspace((uint8_t)*(_p))) _p++
-
/** Zero out any whitespace with nul bytes
*
* @param[in,out] _p string to process
*/
RCSID("$Id$")
-#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/pair.h>
#include <freeradius-devel/util/proto.h>
#include <freeradius-devel/util/regex.h>
--- /dev/null
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Preparse input by skipping known tokens
+ *
+ * @file src/lib/util/skip.c
+ *
+ * @copyright 2025 Network RADIUS SAS (legal@networkradius.com)
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
+#include <freeradius-devel/util/strerror.h>
+
+/** Skip a quoted string.
+ *
+ * @param[in] start start of the string, pointing to the quotation character
+ * @param[in] end end of the string (or NULL for zero-terminated strings)
+ * @return
+ * >0 length of the string which was parsed
+ * <=0 on error
+ */
+ssize_t fr_skip_string(char const *start, char const *end)
+{
+ char const *p = start;
+ char quote;
+
+ quote = *(p++);
+
+ while ((end && (p < end)) || *p) {
+ /*
+ * Stop at the quotation character
+ */
+ if (*p == quote) {
+ p++;
+ return p - start;
+ }
+
+ /*
+ * Not an escape character: it's OK.
+ */
+ if (*p != '\\') {
+ p++;
+ continue;
+ }
+
+ if (end && ((p + 2) >= end)) {
+ fail:
+ fr_strerror_const("Unexpected escape at end of string");
+ return -(p - start);
+ }
+
+ /*
+ * Escape at EOL is not allowed.
+ */
+ if (p[1] < ' ') goto fail;
+
+ /*
+ * \r or \n, etc.
+ */
+ if (!isdigit((uint8_t) p[1])) {
+ p += 2;
+ continue;
+ }
+
+ /*
+ * Double-quoted strings use \000
+ * Regexes use \0
+ */
+ if (quote == '/') {
+ p++;
+ continue;
+ }
+
+ if (end && ((p + 4) >= end)) goto fail;
+
+ /*
+ * Allow for \1f in single quoted strings
+ */
+ if ((quote == '\'') && isxdigit((uint8_t) p[1]) && isxdigit((uint8_t) p[2])) {
+ p += 3;
+ continue;
+ }
+
+ if (!isdigit((uint8_t) p[2]) || !isdigit((uint8_t) p[3])) {
+ fr_strerror_const("Invalid octal escape");
+ return -(p - start);
+ }
+
+ p += 4;
+ }
+
+ /*
+ * Unexpected end of string.
+ */
+ fr_strerror_const("Unexpected end of string");
+ return -(p - start);
+}
+
+/** Skip an xlat expression.
+ *
+ * This is a simple "peek ahead" parser which tries to not be wrong. It may accept
+ * some things which will later parse as invalid (e.g. unknown attributes, etc.)
+ * But it also rejects all malformed expressions.
+ *
+ * It's used as a quick hack because the full parser isn't always available.
+ *
+ * @param[in] start start of the expression, MUST point to the "%{" or "%("
+ * @param[in] end end of the string (or NULL for zero-terminated strings)
+ * @return
+ * >0 length of the string which was parsed
+ * <=0 on error
+ */
+ssize_t fr_skip_xlat(char const *start, char const *end)
+{
+ int depth = 1; /* caller skips '{' */
+ ssize_t slen;
+ char quote, end_quote;
+ char const *p = start;
+
+ /*
+ * At least %{1}
+ */
+ if (end && ((start + 4) > end)) {
+ fr_strerror_const("Invalid expansion");
+ return 0;
+ }
+
+ if ((*p != '%') && (*p != '$')) {
+ fr_strerror_const("Unexpected character in expansion");
+ return -(p - start);
+ }
+
+ p++;
+ if ((*p != '{') && (*p != '(')) {
+ char const *q = p;
+
+ /*
+ * New xlat syntax: %foo(...)
+ */
+ while (isalnum((int) *q) || (*q == '.') || (*q == '_') || (*q == '-')) {
+ q++;
+ }
+ if (*q == '(') {
+ p = q;
+ goto do_quote;
+ }
+
+ fr_strerror_const("Invalid character after '%'");
+ return -(p - start);
+ }
+
+do_quote:
+ quote = *(p++);
+ if (quote == '{') {
+ end_quote = '}';
+ } else {
+ end_quote = ')';
+ }
+
+ while ((end && (p < end)) || (*p >= ' ')) {
+ if (*p == quote) {
+ p++;
+ depth++;
+ continue;
+ }
+
+ if (*p == end_quote) {
+ p++;
+ depth--;
+ if (!depth) return p - start;
+
+ continue;
+ }
+
+ /*
+ * Nested expansion.
+ */
+ if ((p[0] == '$') || (p[0] == '%')) {
+ if (end && (p + 2) >= end) break;
+
+ if ((p[1] == '{') || ((p[0] == '$') && (p[1] == '('))) {
+ slen = fr_skip_xlat(p, end);
+
+ check:
+ if (slen <= 0) return -(p - start) + slen;
+
+ p += slen;
+ continue;
+ }
+
+ /*
+ * Bare $ or %, just leave it alone.
+ */
+ p++;
+ continue;
+ }
+
+ /*
+ * A quoted string.
+ */
+ if ((*p == '"') || (*p == '\'') || (*p == '`')) {
+ slen = fr_skip_string(p, end);
+ goto check;
+ }
+
+ /*
+ * @todo - bare '(' is a condition or nested
+ * expression. The brackets need to balance
+ * here, too.
+ */
+
+ if (*p != '\\') {
+ p++;
+ continue;
+ }
+
+ if (end && ((p + 2) >= end)) break;
+
+ /*
+ * Escapes here are only one-character escapes.
+ */
+ if (p[1] < ' ') break;
+ p += 2;
+ }
+
+ /*
+ * Unexpected end of xlat
+ */
+ fr_strerror_const("Unexpected end of expansion");
+ return -(p - start);
+}
+
+/** Skip a conditional expression.
+ *
+ * This is a simple "peek ahead" parser which tries to not be wrong. It may accept
+ * some things which will later parse as invalid (e.g. unknown attributes, etc.)
+ * But it also rejects all malformed expressions.
+ *
+ * It's used as a quick hack because the full parser isn't always available.
+ *
+ * @param[in] start start of the condition.
+ * @param[in] end end of the string (or NULL for zero-terminated strings)
+ * @param[in] terminal terminal character(s)
+ * @param[out] eol did the parse error happen at eol?
+ * @return
+ * >0 length of the string which was parsed. *eol is false.
+ * <=0 on error, *eol may be set.
+ */
+ssize_t fr_skip_condition(char const *start, char const *end, bool const terminal[static UINT8_MAX + 1], bool *eol)
+{
+ char const *p = start;
+ bool was_regex = false;
+ int depth = 0;
+ ssize_t slen;
+
+ if (eol) *eol = false;
+
+ /*
+ * Keep parsing the condition until we hit EOS or EOL.
+ */
+ while ((end && (p < end)) || *p) {
+ if (isspace((uint8_t) *p)) {
+ p++;
+ continue;
+ }
+
+ /*
+ * In the configuration files, conditions end with ") {" or just "{"
+ */
+ if ((depth == 0) && terminal[(uint8_t) *p]) {
+ return p - start;
+ }
+
+ /*
+ * "recurse" to get more conditions.
+ */
+ if (*p == '(') {
+ p++;
+ depth++;
+ was_regex = false;
+ continue;
+ }
+
+ if (*p == ')') {
+ if (!depth) {
+ fr_strerror_const("Too many ')'");
+ return -(p - start);
+ }
+
+ p++;
+ depth--;
+ was_regex = false;
+ continue;
+ }
+
+ /*
+ * Parse xlats. They cannot span EOL.
+ */
+ if ((*p == '$') || (*p == '%')) {
+ if (end && ((p + 2) >= end)) {
+ fr_strerror_const("Expansions cannot extend across end of line");
+ return -(p - start);
+ }
+
+ if ((p[1] == '{') || ((p[0] == '$') && (p[1] == '('))) {
+ slen = fr_skip_xlat(p, end);
+
+ check:
+ if (slen <= 0) return -(p - start) + slen;
+
+ p += slen;
+ continue;
+ }
+
+ /*
+ * Bare $ or %, just leave it alone.
+ */
+ p++;
+ was_regex = false;
+ continue;
+ }
+
+ /*
+ * Parse quoted strings. They cannot span EOL.
+ */
+ if ((*p == '"') || (*p == '\'') || (*p == '`') || (was_regex && (*p == '/'))) {
+ was_regex = false;
+
+ slen = fr_skip_string((char const *) p, end);
+ goto check;
+ }
+
+ /*
+ * 192.168/16 is a netmask. So we only
+ * allow regex after a regex operator.
+ *
+ * This isn't perfect, but is good enough
+ * for most purposes.
+ */
+ if ((p[0] == '=') || (p[0] == '!')) {
+ if (end && ((p + 2) >= end)) {
+ fr_strerror_const("Operators cannot extend across end of line");
+ return -(p - start);
+ }
+
+ if (p[1] == '~') {
+ was_regex = true;
+ p += 2;
+ continue;
+ }
+
+ /*
+ * Some other '==' or '!=', just leave it alone.
+ */
+ p++;
+ was_regex = false;
+ continue;
+ }
+
+ /*
+ * Any control characters (other than \t) cause an error.
+ */
+ if (*p < ' ') break;
+
+ was_regex = false;
+
+ /*
+ * Normal characters just get skipped.
+ */
+ if (*p != '\\') {
+ p++;
+ continue;
+ }
+
+ /*
+ * Backslashes at EOL are ignored.
+ */
+ if (end && ((p + 2) >= end)) break;
+
+ /*
+ * Escapes here are only one-character escapes.
+ */
+ if (p[1] < ' ') break;
+ p += 2;
+ }
+
+ /*
+ * We've fallen off of the end of a string. It may be OK?
+ */
+ if (eol) *eol = (depth > 0);
+
+ if (terminal[(uint8_t) *p]) return p - start;
+
+ fr_strerror_const("Unexpected end of condition");
+ return -(p - start);
+}
+
--- /dev/null
+#pragma once
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Preparse input by skipping known tokens
+ *
+ * @file src/lib/util/skip.h
+ *
+ * @copyright 2001,2006 The FreeRADIUS server project
+ */
+RCSIDH(skip_h, "$Id$")
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Skip whitespace ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
+ *
+ * @param[in,out] _p string to skip over.
+ */
+#define fr_skip_whitespace(_p) while(isspace((uint8_t)*(_p))) _p++
+
+/** Skip whitespace, stopping at end ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
+ *
+ * @param[in,out] _p string to skip over.
+ * @param[in] _e pointer to end of string.
+ */
+#define fr_bskip_whitespace(_p, _e) while((_p < _e) && isspace((uint8_t)*(_p))) _p++
+
+/** Skip everything that's not whitespace ('\\t', '\\n', '\\v', '\\f', '\\r', ' ')
+ *
+ * @param[in,out] _p string to skip over.
+ */
+#define fr_skip_not_whitespace(_p) while(*_p && !isspace((uint8_t)*(_p))) _p++
+
+ssize_t fr_skip_string(char const *start, char const *end) CC_HINT(nonnull(1));
+
+ssize_t fr_skip_xlat(char const *start, char const *end) CC_HINT(nonnull(1));
+
+ssize_t fr_skip_condition(char const *start, char const *end, bool const terminal[static UINT8_MAX + 1],
+ bool *eol) CC_HINT(nonnull(1,3));
+#ifdef __cplusplus
+}
+#endif
#include <freeradius-devel/autoconf.h>
#include <freeradius-devel/util/time.h>
-#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/skip.h>
int64_t const fr_time_multiplier_by_res[] = {
[FR_TIME_RES_NSEC] = 1,
*/
RCSID("$Id$")
-#include <freeradius-devel/util/misc.h>
+#include <stdio.h>
+
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/strerror.h>
#include <freeradius-devel/util/token.h>
{
return fr_table_str_by_value(fr_tokens_table, token, "<INVALID>");
}
-
-
-/** Skip a quoted string.
- *
- * @param[in] start start of the string, pointing to the quotation character
- * @param[in] end end of the string (or NULL for zero-terminated strings)
- * @return
- * >0 length of the string which was parsed
- * <=0 on error
- */
-ssize_t fr_skip_string(char const *start, char const *end)
-{
- char const *p = start;
- char quote;
-
- quote = *(p++);
-
- while ((end && (p < end)) || *p) {
- /*
- * Stop at the quotation character
- */
- if (*p == quote) {
- p++;
- return p - start;
- }
-
- /*
- * Not an escape character: it's OK.
- */
- if (*p != '\\') {
- p++;
- continue;
- }
-
- if (end && ((p + 2) >= end)) {
- fail:
- fr_strerror_const("Unexpected escape at end of string");
- return -(p - start);
- }
-
- /*
- * Escape at EOL is not allowed.
- */
- if (p[1] < ' ') goto fail;
-
- /*
- * \r or \n, etc.
- */
- if (!isdigit((uint8_t) p[1])) {
- p += 2;
- continue;
- }
-
- /*
- * Double-quoted strings use \000
- * Regexes use \0
- */
- if (quote == '/') {
- p++;
- continue;
- }
-
- if (end && ((p + 4) >= end)) goto fail;
-
- /*
- * Allow for \1f in single quoted strings
- */
- if ((quote == '\'') && isxdigit((uint8_t) p[1]) && isxdigit((uint8_t) p[2])) {
- p += 3;
- continue;
- }
-
- if (!isdigit((uint8_t) p[2]) || !isdigit((uint8_t) p[3])) {
- fr_strerror_const("Invalid octal escape");
- return -(p - start);
- }
-
- p += 4;
- }
-
- /*
- * Unexpected end of string.
- */
- fr_strerror_const("Unexpected end of string");
- return -(p - start);
-}
-
fr_token_t getop(char const **ptr);
fr_token_t getstring(char const **ptr, char *buf, int buflen, bool unescape);
char const *fr_token_name(int);
-ssize_t fr_skip_string(char const *start, char const *end);
#ifdef __cplusplus
}
RCSID("$Id$")
#include <freeradius-devel/util/dict.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/syserror.h>
#include <freeradius-devel/util/trie.h>
#include <freeradius-devel/util/conf.h>
#include <freeradius-devel/util/md5.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/socket.h>
#include <freeradius-devel/util/atexit.h>
#include <freeradius-devel/io/application.h>
#include <freeradius-devel/io/listen.h>
#include <freeradius-devel/io/schedule.h>
+#include <freeradius-devel/util/skip.h>
#include "lib/server/cf_util.h"
#include "proto_cron.h"
#include <freeradius-devel/server/module_rlm.h>
#include <freeradius-devel/dhcpv4/dhcpv4.h>
#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/server/map_proc.h>
#include <freeradius-devel/server/pool.h>
#include <freeradius-devel/server/tmpl.h>
#include <freeradius-devel/unlang/call.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/value.h>
#include <talloc.h>
#include <freeradius-devel/server/pairmove.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/dict.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/table.h>
#include <freeradius-devel/unlang/function.h>
#include <freeradius-devel/unlang/xlat_func.h>
#include <freeradius-devel/radius/radius.h>
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/server/module_rlm.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/perm.h>
#include <freeradius-devel/unlang/xlat_func.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/unlang/xlat.h>
#include <freeradius-devel/util/dcursor.h>
+#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/value.h>
#include "rlm_winbind.h"