summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/format.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/format.c b/src/format.c
index 9871ac6..9c25d4c 100644
--- a/src/format.c
+++ b/src/format.c
@@ -2900,6 +2900,112 @@ format_link(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
+/* Eliminate duplicate values from the list. */
+static int
+format_unique(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)
+{
+ int ret, i, j, argc;
+ char **argv, **values;
+ const char *value_format, *default_value;
+ unsigned int *lengths;
+ struct berval **choices, bv;
+
+ ret = format_parse_args(state, args, &argc, &argv);
+ if (ret != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "unique: error parsing arguments\n");
+ return -EINVAL;
+ }
+ if (argc < 1) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "unique: error parsing arguments\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
+ if (argc < 2) {
+ value_format = argv[0];
+ default_value = NULL;
+ } else {
+ value_format = argv[0];
+ default_value = argv[1];
+ }
+ ret = -ENOENT;
+ values = format_get_data_set(state, e, group, set,
+ value_format, disallowed,
+ rel_attrs, ref_attrs, inref_attrs,
+ ref_attr_list, inref_attr_list,
+ &lengths);
+ if (values == NULL) {
+ if (default_value == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "unique: no values for ->%s<-, "
+ "and no default value provided\n",
+ value_format);
+ ret = -ENOENT;
+ } else {
+ i = format_expand(state, pb, e,
+ group, set,
+ default_value, NULL,
+ outbuf, outbuf_len,
+ outbuf_choices,
+ rel_attrs, ref_attrs, inref_attrs,
+ ref_attr_list, inref_attr_list);
+ ret = i;
+ }
+ } else {
+ if (values != NULL) {
+ choices = NULL;
+ for (i = 0; values[i] != NULL; i++) {
+ /* XXX this is horribly slow */
+ for (j = 0; j < i; j++) {
+ if ((lengths[i] == lengths[j]) &&
+ (memcmp(values[i], values[j], lengths[i]) == 0)) {
+ break;
+ }
+ }
+ if (j == i) {
+ /* Add it to the list. */
+ bv.bv_val = values[i];
+ bv.bv_len = lengths[i];
+ format_add_bv_list(&choices, &bv);
+ }
+ }
+ format_free_data_set(values, lengths);
+ if (choices != NULL) {
+ for (i = 0; choices[i] != NULL; i++) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "unique: returning \"%.*s\" as a "
+ "value for \"%s\"\n",
+ (int) choices[i]->bv_len,
+ choices[i]->bv_val,
+ slapi_entry_get_dn(e));
+ continue;
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "unique: returning %d values for \"%s\"\n", i,
+ slapi_entry_get_dn(e));
+ format_add_choice(outbuf_choices, outbuf, &choices);
+ ret = 0;
+ } else {
+ ret = -ENOENT;
+ }
+ }
+ }
+ format_free_parsed_args(argv);
+ return ret;
+}
+
/* Choose a formatting function by name. */
static void *
format_lookup_fn(const char *fnname)
@@ -2936,6 +3042,8 @@ format_lookup_fn(const char *fnname)
{"ifeq", format_ifeq},
{"collect", format_collect},
{"link", format_link},
+ {"unique", format_unique},
+ /* {"uuid", format_uuid}, */
};
for (i = 0; i < sizeof(fns) / sizeof(fns[0]); i++) {
if ((fns[i].name != NULL) &&