]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add and document support for tripled-quoted strings
authorAlan T. DeKok <aland@freeradius.org>
Fri, 22 Nov 2024 15:38:33 +0000 (10:38 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 22 Nov 2024 15:39:28 +0000 (10:39 -0500)
secret = """foo " bar " baz ! """

doc/antora/modules/reference/pages/type/all_types.adoc
doc/antora/modules/reference/pages/type/index.adoc
doc/antora/modules/reference/pages/type/string/double.adoc
doc/antora/modules/reference/pages/type/string/single.adoc
src/lib/server/tmpl_tokenize.c
src/lib/util/token.c

index ec772f7db128d3adaf180992d69d4778c9e89ee6..3e5392870d2da7f4e7f182a31715a363ffece5f9 100644 (file)
@@ -36,7 +36,7 @@ possible to write values in the format you expect, The server will do
 | ipv4prefix    | IPv4 network with address and prefix length
 | ipv6prefix    | IPv6 network with address and prefix length
 | octets        | raw binary, printed as hex strings
-| string        | printable strings
+| xref:type/string/index.adoc[string]        | printable strings
 | time_delta   | difference between two calendar dates
 | uint8                | 8-bit unsigned integer
 | uint16       | 16-bit unsigned integer
index cfdbd7faf33c5b3842af01a348f4d6e2c6ca18e8..0f66ce4918ff3032e8fc1f2068a77c2e700281bb 100644 (file)
@@ -1,7 +1,7 @@
 = Data Types
 
 Unlang supports a number of data types. These data types are used in
-conditional expressions or when assigning a value to an attribute.
+dictionaries, expressions or when assigning a value to an attribute.
 
 == Using Data Types
 
index 8df6661da8e22d6225a23affcec99d35e1746011..fafcd2b0119a106e7fde8aab99549858f10b05a9 100644 (file)
@@ -8,6 +8,14 @@ xref:xlat/index.adoc[dynamic expansions]. As with
 xref:type/string/single.adoc[single-quoted strings], text within
 double quotes can include spaces.
 
+For normally quoted strings, the quotation character can be placed inside of
+the string by escaping it with a backslash.
+
+For triple quoted strings, the quotation character does not need to be
+escaped.  However, if the string does contain an escaped quotation
+character, the quotation character is unescaped, as with normally
+quoted strings.
+
 The main difference between the single and double quoted strings is
 that the double quoted strings can be dynamically expanded. The syntax
 `${...}` is used for parse-time expansion and `%{...}` is used for
@@ -133,6 +141,7 @@ string is being used.
 `"this has embedded\ncharacters"` +
 `"attribute\tvalue\nusername\t%{User-Name}\nreply-message\t%{reply.Reply-Message}"`
 `"The result of 'SELECT * FROM foo WHERE 1' is: %sql(SELECT * FROM foo WHERE 1)"`
+`"""this string has a "double quoted" string in the middle of it"""`
 
 // Licenced under CC-by-NC 4.0.
 // Copyright (C) 2019 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
index fb4b9a4b208ce0f4e94cf99f530214fd54f080ea..2a91f325163e45ee6507c4e01e335075740854b5 100644 (file)
@@ -2,11 +2,19 @@
 
 .Syntax
 `'string'`
+`'''string with 'quote' embedded'''`
 
 A single-quoted string is interpreted without any dynamic string
 expansion. The quotes allow the string to contain spaces, among other
-special characters. The single quote character can be placed in such a
-string by escaping it with a backslash.
+special characters.
+
+For normally quoted strings, the quotation character can be placed inside of
+the string by escaping it with a backslash.
+
+For triple quoted strings, the quotation character does not need to be
+escaped.  However, if the string does contain an escaped quotation
+character, the quotation character is unescaped, as with normally
+quoted strings.
 
 .Examples
 
@@ -14,6 +22,7 @@ string by escaping it with a backslash.
 `'foo bar`' +
 `'foo\\'bar'` +
 `'this is a long string'`
+`'''This is a string with 'embedded' quotes'''`
 
 // Copyright (C) 2021 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // This documentation was developed by Network RADIUS SAS.
index 9a9e88e54d65995fbc0c506f45717065352ec2f2..b8c6088f9d9f4341e692cee4b322c16ccbb5f59f 100644 (file)
@@ -5352,6 +5352,7 @@ ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t i
        char quote;
        char close;
        int depth;
+       bool triple;
 
        *type = T_INVALID;
 
@@ -5496,8 +5497,17 @@ ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t i
                 *      more rigorous check.
                 */
        skip_string:
+               if ((inlen > 3) && (p[0] == quote) && (p[1] == quote)) {
+                       triple = true;
+                       p += 2;
+               } else {
+                       triple = false;
+               }
                *out = p;
+
                while (*p) {
+                       if (p >= end) goto unterminated;
+
                        /*
                         *      End of string.  Tell the caller the
                         *      length of the data inside of the
@@ -5505,9 +5515,21 @@ ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t i
                         *      characters to skip.
                         */
                        if (*p == quote) {
-                               *outlen = p - (*out);
+                               if (!triple) {
+                                       *outlen = p - (*out);
+                                       p++;
+                                       return p - in;
+
+                               }
+
+                               if (((end - p) >= 3) && (p[1] == quote) && (p[2] == quote)) {
+                                       *outlen = p - (*out);
+                                       p += 3;
+                                       return p - in;
+                               }
+
                                p++;
-                               return p - in;
+                               continue;
                        }
 
                        if (*p == '\\') {
@@ -5523,6 +5545,7 @@ ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t i
                 *      End of input without end of string.
                 *      Point the error to the start of the string.
                 */
+               unterminated:
                p = *out;
                return_P("Unterminated string");
 
index c7fa61e9893dbec45e3d4730b865f6d1507c0785..3c063dda7a7ca41e0fa7c60c564e67e3fb7f3db5 100644 (file)
@@ -256,6 +256,7 @@ static fr_token_t getthing(char const **ptr, char *buf, int buflen, bool tok,
        char                    *s;
        char const              *p;
        char                    quote;
+       bool                    triple = false;
        unsigned int            x;
        size_t                  i;
        fr_token_t              token;
@@ -315,6 +316,14 @@ static fr_token_t getthing(char const **ptr, char *buf, int buflen, bool tok,
 
        if (token != T_BARE_WORD) {
                quote = *p;
+
+               /*
+                *      Triple-quoted strings are copied over verbatim, without escapes.
+                */
+               if ((buflen >= 3) && (p[1] == quote) && (p[2] == quote)) {
+                       p += 3;
+               }
+
                p++;
        }
        s = buf;
@@ -350,9 +359,21 @@ static fr_token_t getthing(char const **ptr, char *buf, int buflen, bool tok,
                 *      Un-escaped quote character.  We're done.
                 */
                if (*p == quote) {
-                       p++;
-                       *s++ = 0;
-                       goto done;
+                       if (!triple) {
+                               p++;
+                               *s++ = 0;
+                               goto done;
+
+                       }
+
+                       if ((buflen >= 3) && (p[1] == quote) && (p[2] == quote)) {
+                               p += 3;
+                               *s++ = 0;
+                               goto done;
+                       }
+
+                       *s++ = *p++;
+                       continue;
                }
 
                /*