]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
make prepend work, and update doecs and tests to match
authorAlan T. DeKok <aland@freeradius.org>
Sat, 27 Aug 2022 12:52:18 +0000 (08:52 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 28 Aug 2022 14:56:11 +0000 (10:56 -0400)
doc/antora/modules/reference/pages/unlang/edit.adoc
src/lib/util/calc.c
src/tests/keywords/edit-string [new file with mode: 0644]

index d16dc720f7179f9682c7ea36ea687d22b0e554f6..34ce7d4237c10b20b17040afed6c25cbf2f0ab17 100644 (file)
@@ -391,12 +391,18 @@ The operators also apply to variable-sized values.
 | :=       | Override the attribute with the contents with the _<rhs>_.  If the attribute already exists, its value is over-written.  If the attribute does not exist, it is created, and the contents set to thex value of the _<rhs>_
 | +=       | Perform string append.  The contents of the _<rhs>_ are appended to the _<attribute>_.
 | -=       | Inverse of string append. The contents of the _<rhs>_ are deleted from from the _<attribute>_, if the `_<rhs>_` is a suffix of _<attribute>_ 
-| ^=       | Perform logical "xor".  The contents of the _<rhs>_ are "xor"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
-| \|=       | Perform logical "or".  The value of the _<attribute>_ is "or"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
-| &=        | Perform logical "and".  The value of the _<attribute>_ is "and"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
-| <\<=       | Perform left shift / truncation.  The first _<rhs>_ bytes of _<attribute>_ are dropped. i.e. shifted off of the start of the string.
-| >>=       | Perform right shift / truncation.  The last _<rhs>_ bytes of _<attribute>_ are dropped. i.e. shifted off of the end of the string.
+| ^=       | For `string`, performs a "prepend" operation.  The contents of the _<rhs>_ are prepended to the _<attribute>_.  This is the opposite of `+=`.
+|          | For `octets`, perform logical "xor".  The value of the _<attribute>_ is "or"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
+| \|=      | Perform logical "or".  The value of the _<attribute>_ is "or"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
+| &=       | Perform logical "and".  The value of the _<attribute>_ is "and"ed with the contents of the _<rhs>_.  Both strings must be of the same length.
+| <\<=     | Perform left shift / truncation.  The first _<rhs>_ bytes of _<attribute>_ are dropped. i.e. shifted off of the start of the string.
+| >>=      | Perform right shift / truncation.  The last _<rhs>_ bytes of _<attribute>_ are dropped. i.e. shifted off of the end of the string.
 |=====
 
+Note that the `^=` operator behaves differently for `string` and
+`octets`.  The output of "xor"ing two strings is likely to be binary
+data, and therefore not a printable string.  As a result, it is more
+useful for strings to have `^-` be a "prepend" operation.
+
 // Copyright (C) 2021 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // Development of this documentation was sponsored by Network RADIUS SAS.
index 276db9e8bd50285f35a9a5cd634db1dc63e384a7..6043502c315fa920cccbae8a07a67805293e6179 100644 (file)
@@ -966,6 +966,18 @@ static int calc_string(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t cons
                fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted);
                break;
 
+       case T_XOR:             /* is prepend for strings */
+               buf = talloc_array(ctx, char, len + 1);
+               if (!buf) goto oom;
+
+               len = a->vb_length + b->vb_length;
+               memcpy(buf, b->vb_strvalue, b->vb_length);
+               memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
+               buf[len] = '\0';
+
+               fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted);
+               break;
+
        case T_SUB:
                /*
                 *  The inverse of add!
diff --git a/src/tests/keywords/edit-string b/src/tests/keywords/edit-string
new file mode 100644 (file)
index 0000000..e93921b
--- /dev/null
@@ -0,0 +1,27 @@
+#
+#  PRE: edit
+#
+&Tmp-String-0 := "foo"
+&Tmp-String-0 ^= "bar"
+
+if (&Tmp-String-0 != "barfoo") {
+       test_fail
+}
+
+&Tmp-String-0 := "foo"
+&Tmp-String-0 += "bar"
+
+if (&Tmp-String-0 != "foobar") {
+       test_fail
+}
+
+#
+#  Subtract is the inverse of add.
+#
+&Tmp-String-0 -= "bar"
+
+if (&Tmp-String-0 != "foo") {
+       test_fail
+}
+
+success