summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--doc/format-specifiers.txt10
-rw-r--r--src/format.c86
-rwxr-xr-xtests/test23-schema-link/before.sh1
-rw-r--r--tests/test23-schema-link/before.txt14
-rw-r--r--tests/test23-schema-link/dse.ldif14
6 files changed, 87 insertions, 40 deletions
diff --git a/NEWS b/NEWS
index 0073ae1..995529a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+0.40 * Treat the pad values passed to %link as expressions rather than
+ mere literal strings (part of #767372).
0.39 * Populate the entryUSN value in entries with either the value from
the source entry or the root DSE.
* Add a default function (part of #767372).
diff --git a/doc/format-specifiers.txt b/doc/format-specifiers.txt
index f37ce9a..7dca9db 100644
--- a/doc/format-specifiers.txt
+++ b/doc/format-specifiers.txt
@@ -555,11 +555,11 @@ And here's how some example expressions evaluate for ''cn=group'':
link(''EXPRESSION'',''PAD''[,''SEPARATOR'',''EXPRESSION2'',''PAD2''[,...])
-Evaluates each ''EXPRESSION'' in turn to produce a list of values. If
-the lists produced by each of the expressions are not of the same
-length, then each ''EXPRESSION'''s corresponding ''PAD'' value is
-appended to each list, padding them out until they are all of equal
-length (i.e., the length of the longest list).
+Evaluates each ''EXPRESSION'' and ''PAD'' in turn to produce a list of
+values. If the lists produced by each of the expressions are not of the
+same length, then each ''EXPRESSION'''s corresponding ''PAD'' value is
+appended to each list to pad them out until they are all of equal length
+(i.e., the length of the longest list).
Then, one list of values is produced by using the first value from each
list (separated by the corresponding SEPARATOR), then using the second
diff --git a/src/format.c b/src/format.c
index aed71f1..ee85b6f 100644
--- a/src/format.c
+++ b/src/format.c
@@ -2588,15 +2588,15 @@ format_regsubi(struct plugin_state *state,
}
static int
format_mregsubi(struct plugin_state *state,
- Slapi_PBlock *pb, Slapi_Entry *e,
- const char *group, const char *set,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
- struct format_choice **outbuf_choices,
- char ***rel_attrs, char ***ref_attrs,
- struct format_inref_attr ***inref_attrs,
- struct format_ref_attr_list ***ref_attr_list,
- struct format_ref_attr_list ***inref_attr_list)
+ Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *group, const char *set,
+ const char *args, const char *disallowed,
+ char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
+ char ***rel_attrs, char ***ref_attrs,
+ struct format_inref_attr ***inref_attrs,
+ struct format_ref_attr_list ***ref_attr_list,
+ struct format_ref_attr_list ***inref_attr_list)
{
return format_match_generic(state, pb, e, group, set, args, 3, -1,
disallowed,
@@ -2898,9 +2898,9 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
/* Allocate space to store the information. */
- values = malloc(sizeof(char **) * ((argc + 1) / 3));
- lengths = malloc(sizeof(int *) * ((argc + 1) / 3));
- n_items = malloc(sizeof(int) * ((argc + 1) / 3));
+ values = malloc(sizeof(char **) * (((argc + 1) / 3) * 2));
+ lengths = malloc(sizeof(int *) * (((argc + 1) / 3) * 2));
+ n_items = malloc(sizeof(int) * (((argc + 1) / 3) * 2));
if ((values == NULL) || (lengths == NULL) || (n_items == NULL)) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"link: out of memory\n");
@@ -2917,14 +2917,28 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
for (i = 0; i < argc; i += 3) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"link: evaluating \"%s\"\n", argv[i]);
- values[i / 3] = format_get_data_set(state, pb, e, group, set,
- argv[i], disallowed,
- rel_attrs,
- ref_attrs, inref_attrs,
- ref_attr_list,
- inref_attr_list,
- &lengths[i / 3]);
- if (values[i / 3] != NULL) {
+ j = (i / 3) * 2;
+ values[j] = format_get_data_set(state, pb, e, group, set,
+ argv[i], disallowed,
+ rel_attrs,
+ ref_attrs, inref_attrs,
+ ref_attr_list,
+ inref_attr_list,
+ &lengths[j]);
+ if (values[j] != NULL) {
+ n_lists++;
+ }
+ j++;
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "link: evaluating \"%s\"\n", argv[i + 1]);
+ values[j] = format_get_data_set(state, pb, e, group, set,
+ argv[i + 1], disallowed,
+ rel_attrs,
+ ref_attrs, inref_attrs,
+ ref_attr_list,
+ inref_attr_list,
+ &lengths[j]);
+ if (values[j] != NULL) {
n_lists++;
}
}
@@ -2939,7 +2953,7 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
/* Walk the lists, building the output data items. */
- n_lists = (argc + 1) / 3;
+ n_lists = ((argc + 1) / 3) * 2;
/* Count the number of items in each list. */
for (i = 0; i < n_lists; i++) {
for (j = 0;
@@ -2953,28 +2967,30 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
buffer = NULL;
length = 0;
n_done = 0;
- for (result_n = 0; n_done < n_lists; result_n++) {
+ for (result_n = 0; n_done < (n_lists / 2); result_n++) {
/* Calculate how much space we need for this result. */
length = 0;
n_done = 0;
- for (i = 0; i < n_lists; i++) {
+ for (i = 0; i < n_lists; i += 2) {
if (result_n < n_items[i]) {
/* This list has an item for this result. */
length += lengths[i][result_n];
} else {
- /* This list ran out of items -- use padding. */
- length += strlen(argv[i * 3 + 1]);
+ /* This list ran out of items -- use a value
+ * from the pad result list. */
+ length += lengths[i + 1][result_n %
+ n_items[i + 1]];
/* Note that this list has run out. */
n_done++;
}
- if (i < (n_lists - 1)) {
+ if (i < (n_lists - 2)) {
/* And the separator. */
- length += strlen(argv[i * 3 + 2]);
+ length += strlen(argv[(i / 2) * 3 + 2]);
}
}
/* If we're out of data, we should stop before adding a result
* to the list. */
- if (n_done == n_lists) {
+ if (n_done == n_lists / 2) {
break;
}
/* Make sure the buffer is large enough. */
@@ -2997,7 +3013,7 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
/* Build the output value. */
p = buffer;
- for (i = 0; i < n_lists; i++) {
+ for (i = 0; i < n_lists; i += 2) {
if (result_n < n_items[i]) {
/* This list has an item for this result. */
l = lengths[i][result_n];
@@ -3005,14 +3021,16 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
p += l;
} else {
/* This list ran out of items -- use padding. */
- l = strlen(argv[i * 3 + 1]);
- memcpy(p, argv[i * 3 + 1], l);
+ l = lengths[i + 1][result_n %
+ n_items[i + 1]];
+ memcpy(p, values[i + 1][result_n %
+ n_items[i + 1]], l);
p += l;
}
- if (i < (n_lists - 1)) {
+ if (i < (n_lists - 2)) {
/* Separator. */
- l = strlen(argv[i * 3 + 2]);
- memcpy(p, argv[i * 3 + 2], l);
+ l = strlen(argv[(i / 2) * 3 + 2]);
+ memcpy(p, argv[(i / 2) * 3 + 2], l);
p += l;
}
}
diff --git a/tests/test23-schema-link/before.sh b/tests/test23-schema-link/before.sh
index 4f0e0b7..7b1606b 100755
--- a/tests/test23-schema-link/before.sh
+++ b/tests/test23-schema-link/before.sh
@@ -1,2 +1,3 @@
#!/bin/sh
search -b cn=compat,cn=accounts,dc=example,dc=com dn thingy | $LDIFSORT
+search -b cn=compat2,cn=accounts,dc=example,dc=com dn thingy | $LDIFSORT
diff --git a/tests/test23-schema-link/before.txt b/tests/test23-schema-link/before.txt
index abd7230..81a0235 100644
--- a/tests/test23-schema-link/before.txt
+++ b/tests/test23-schema-link/before.txt
@@ -22,3 +22,17 @@ thingy: -,user1c,user1c,user1c|user1c
thingy: -,-,user1c,user1c|user1c
thingy: -,-,-,user1c|user1c
+dn: cn=compat2,cn=accounts,dc=example,dc=com
+
+dn: cn=example,cn=compat2,cn=accounts,dc=example,dc=com
+
+dn: uid=group1-fake-uid,cn=example,cn=compat2,cn=accounts,dc=example,dc=com
+thingy: -,group1-fake-uid,group1-fake-uid,group1-fake-uid
+thingy: -,group1,group1-fake-uid,group1-fake-uid
+thingy: -,group1,group1,group1-fake-uid
+
+dn: uid=group2-fake-uid,cn=example,cn=compat2,cn=accounts,dc=example,dc=com
+thingy: -,group2-fake-uid,group2-fake-uid,group2-fake-uid
+thingy: -,group2-alternate-name,group2-fake-uid,group2-fake-uid
+thingy: -,group2,group2,group2-fake-uid
+
diff --git a/tests/test23-schema-link/dse.ldif b/tests/test23-schema-link/dse.ldif
index a36146a..45b4bd3 100644
--- a/tests/test23-schema-link/dse.ldif
+++ b/tests/test23-schema-link/dse.ldif
@@ -1,4 +1,4 @@
-dn: cn=example,cn=Schema Compatibility,cn=plugins,cn=config
+dn: cn=example+cn="compat,cn=Accounts,dc=example,dc=com",cn=Schema Compatibility,cn=plugins,cn=config
objectClass: top
objectClass: extensibleObject
cn: example
@@ -10,3 +10,15 @@ schema-compat-search-filter: (objectClass=posixAccount)
schema-compat-entry-rdn: uid=%{uid}
schema-compat-entry-attribute: thingy=%link("%{madeup}", "-", ",", "%merge(\":\",\"%{uid}\",\"%{madeup}\")", "-", ",", "%collect(\"%{uid}\",\"%{madeup}\",\"%{uid}\")", "-", ",", "%collect(\"%{madeup}\",\"%{uid}\",\"%{madeup}\",\"%{uid}\",\"%deref(\\\"madeup\\\",\\\"madeup\\\")\",\"%{uid}\")", "-")|%{uid}
+dn: cn=example+cn="compat2,cn=Accounts,dc=example,dc=com",cn=Schema Compatibility,cn=plugins,cn=config
+objectClass: top
+objectClass: extensibleObject
+cn: example
+schema-compat-container-group: cn=compat2,cn=Accounts,dc=example,dc=com
+schema-compat-container-rdn: cn=example
+schema-compat-check-access: yes
+schema-compat-search-base: cn=Groups1, cn=Accounts, dc=example, dc=com
+schema-compat-search-filter: (objectClass=posixGroup)
+schema-compat-entry-rdn: uid=%{uid}
+schema-compat-entry-attribute: thingy=%link("%{madeup}", "-", ",", "%merge(\":\",\"%{uid}\",\"%{madeup}\")", "%{cn}", ",", "%collect(\"%{uid}\",\"%{madeup}\",\"%{uid}\")", "%{cn}", ",", "%collect(\"%{madeup}\",\"%{uid}\",\"%{madeup}\",\"%{uid}\",\"%deref(\\\"madeup\\\",\\\"madeup\\\")\",\"%{uid}\")", "-")
+