summaryrefslogtreecommitdiffstats
path: root/src/format.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-10-24 13:54:46 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-10-24 13:54:46 -0400
commit316ece9f122d3ee63e84734cf4b790c691963e04 (patch)
tree9f06d9ff8e13a68220d6d2e012d07338f7a005ca /src/format.c
parentaf009c9d84d37ab5880f575efcddbae782fe64d1 (diff)
- add referredx, as derefx
Diffstat (limited to 'src/format.c')
-rw-r--r--src/format.c319
1 files changed, 318 insertions, 1 deletions
diff --git a/src/format.c b/src/format.c
index 01590d9..8da0a68 100644
--- a/src/format.c
+++ b/src/format.c
@@ -287,7 +287,9 @@ format_add_ref_attr_list(struct format_ref_attr_list ***list,
if (format_find_ref_attr_list(*list, group, set, names) != NULL) {
return *list;
}
- for (i = 0; (list != NULL) && (list[i] != NULL); i++) {
+ for (i = 0;
+ (list != NULL) && (*list != NULL) && ((*list)[i] != NULL);
+ i++) {
continue;
}
ret = malloc((i + 2) * sizeof(struct format_ref_attr_list*));
@@ -1341,6 +1343,320 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return 0;
}
+/* Add the name of this entry to the DN list in the cbdata. */
+struct format_note_entry_sdn_cbdata {
+ struct plugin_state *state;
+ Slapi_DN ***sdn_list;
+};
+
+static int
+format_note_entry_sdn_cb(Slapi_Entry *e, void *cbdata_ptr)
+{
+ struct format_note_entry_sdn_cbdata *cbdata = cbdata_ptr;
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
+ "search matched entry \"%s\"\n", slapi_entry_get_dn(e));
+ format_add_sdn_list(cbdata->sdn_list, slapi_entry_get_dn(e));
+ return 0;
+}
+
+/* For the first N-1 arguments, treat them as pairs, looking entries in the
+ * map named by the first part of the pair which refer to this entry using the
+ * attribute named by the second part in the pair, following links until we
+ * get to the last argument, at which point we return the value of the
+ * attribute named by the final argument. */
+static int
+format_referredx(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 ***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 i, j, k, ret, argc, attrs_list_length, disposition, buffer_flags;
+ Slapi_PBlock *local_pb;
+ Slapi_DN **these_bases, **next_bases, **these_entries, **next_entries;
+ Slapi_Entry *entry;
+ Slapi_ValueSet *values;
+ Slapi_Value *value;
+ struct berval **choices;
+ const struct berval *bval;
+ struct format_note_entry_sdn_cbdata note_cbdata;
+ struct format_ref_attr_list *list;
+ char **argv, *attrs[2], *filter, *tndn, *attr, *other_attr;
+ char *actual_attr;
+ char *other_set, *set_filter, **set_bases, *use_filter;
+ const char **attr_links, *ndn;
+
+ ret = format_parse_args(state, args, &argc, &argv);
+ if (ret != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: error parsing arguments\n");
+ return -EINVAL;
+ }
+ if (argc < 3) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: requires at least 3 arguments\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
+ if ((argc % 2) != 1) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: requires an odd number of "
+ "arguments\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
+ if (outbuf_choices == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: returns a list, but a list would "
+ "not be appropriate here\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
+ other_set = argv[0];
+ other_attr = argv[1];
+ attr = argv[2];
+
+ /* Build the list of attributes which we can use to select the list of
+ * references. */
+ attrs_list_length = (argc + 1) / 2;
+ attr_links = malloc((attrs_list_length + 1) * sizeof(char *));
+ if (attr_links == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: out of memory\n");
+ format_free_parsed_args(argv);
+ return -ENOMEM;
+ }
+ for (i = 0; i < attrs_list_length; i++) {
+ if (i < (attrs_list_length - 1)) {
+ attr_links[i] = argv[i * 2 + 1];
+ } else {
+ attr_links[i] = argv[i * 2];
+ }
+ }
+ attr_links[i] = NULL;
+
+ /* Note this list of attributes. */
+ format_add_ref_attr_list(inref_attr_list, group, set, attr_links);
+ list = format_find_ref_attr_list(*inref_attr_list, group, set,
+ attr_links);
+ free(attr_links);
+
+ /* Set up to search for referrers. */
+ local_pb = slapi_pblock_new();
+ if (local_pb == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referredx: out of memory\n");
+ format_free_parsed_args(argv);
+ return -ENOMEM;
+ }
+
+ /* Get the searching parameters for the set which contains the entry,
+ * and all of the referred-to sets, and save them for use at the last
+ * link in the chain. */
+ backend_get_set_config(state, group, set,
+ &set_bases, &set_filter);
+ for (i = 0; (set_bases != NULL) && (set_bases[i] != NULL); i++) {
+ format_add_sdn_list(&(list->links[0].base_sdn_list),
+ set_bases[i]);
+ }
+ backend_free_set_config(set_bases, set_filter);
+ for (i = 0; i < list->n_links - 1; i++) {
+ backend_get_set_config(state, group, argv[i * 2],
+ &set_bases, &set_filter);
+ for (j = 0;
+ (set_bases != NULL) && (set_bases[j] != NULL);
+ j++) {
+ format_add_sdn_list(&(list->links[i + 1].base_sdn_list),
+ set_bases[j]);
+ }
+ backend_free_set_config(set_bases, set_filter);
+ }
+
+ /* Walk the chain, searching for entries which refer to entries at
+ * this point in the chain. */
+ these_entries = NULL;
+ format_add_sdn_list(&these_entries, slapi_entry_get_dn(e));
+ next_entries = NULL;
+ attrs[0] = NULL;
+ for (i = 0; i < list->n_links - 1; i++) {
+ these_bases = list->links[i].base_sdn_list;
+ if (i < list->n_links - 1) {
+ next_bases = list->links[i + 1].base_sdn_list;
+ } else {
+ next_bases = NULL;
+ }
+ /* Perform the search for entries which refer to each entry we
+ * see here. */
+ for (j = 0;
+ (these_entries != NULL) && (these_entries[j] != NULL);
+ j++) {
+ ndn = slapi_sdn_get_ndn(these_entries[j]);
+ tndn = format_escape_for_filter(ndn);
+ if (tndn == NULL) {
+ continue;
+ }
+ /* Walk the set of search bases for this link. */
+ filter = malloc(strlen(list->links[i].attribute) +
+ strlen(tndn) + 4);
+ if (filter == NULL) {
+ free(tndn);
+ continue;
+ }
+ sprintf(filter, "(%s=%s)",
+ list->links[i].attribute, tndn);
+ for (k = 0;
+ (these_bases != NULL) && (these_bases[k] != NULL);
+ k++) {
+ ndn = slapi_sdn_get_dn(these_bases[k]);
+ /* Search for referrers under this tree. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: searching under %s "
+ "for \"%s\" (link=%d.1)\n",
+ ndn, filter, i);
+ slapi_search_internal_set_pb(local_pb,
+ ndn,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs,
+ FALSE,
+ NULL, NULL,
+ state->plugin_identity,
+ 0);
+ note_cbdata.state = state;
+ note_cbdata.sdn_list = &these_entries;
+ slapi_search_internal_callback_pb(local_pb,
+ &note_cbdata,
+ NULL,
+ format_note_entry_sdn_cb,
+ NULL);
+ }
+ free(filter);
+ /* Walk the set of search bases for the next link. */
+ filter = malloc(strlen(list->links[i].attribute) +
+ strlen(tndn) + 4);
+ if (filter == NULL) {
+ free(tndn);
+ continue;
+ }
+ sprintf(filter, "(%s=%s)",
+ list->links[i].attribute, tndn);
+ for (k = 0;
+ (next_bases != NULL) && (next_bases[k] != NULL);
+ k++) {
+ ndn = slapi_sdn_get_dn(next_bases[k]);
+ /* Search for referrers under that tree. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: searching under %s "
+ "for \"%s\" (link=%d.2)\n",
+ ndn, filter, i);
+ slapi_search_internal_set_pb(local_pb,
+ ndn,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs,
+ FALSE,
+ NULL, NULL,
+ state->plugin_identity,
+ 0);
+ note_cbdata.state = state;
+ note_cbdata.sdn_list = &next_entries;
+ slapi_search_internal_callback_pb(local_pb,
+ &note_cbdata,
+ NULL,
+ format_note_entry_sdn_cb,
+ NULL);
+ }
+ free(filter);
+ free(tndn);
+ }
+ /* Set up for the next iteration. */
+ format_free_sdn_list(these_entries);
+ these_entries = next_entries;
+ next_entries = NULL;
+ }
+
+ /* Walk the list of entries at which we've finally arrived, and
+ * extract the last attribute's value. */
+ attrs[0] = list->links[list->n_links - 1].attribute;
+ attrs[1] = NULL;
+ choices = NULL;
+ for (i = 0;
+ (these_entries != NULL) && (these_entries[i] != NULL);
+ i++) {
+ next_entries = list->links[list->n_links - 1].base_sdn_list;
+ ndn = slapi_sdn_get_ndn(these_entries[i]);
+ format_add_sdn_list(&next_entries, slapi_dn_parent(ndn));
+ list->links[list->n_links - 1].base_sdn_list = next_entries;
+ /* Read the entry. */
+ wrap_search_internal_get_entry(these_entries[i], attrs, &entry,
+ state->plugin_identity);
+ if (entry == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: error reading entry "
+ "\"%s\"\n",
+ slapi_sdn_get_dn(these_entries[i]));
+ continue;
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: reading \"%s\" from entry "
+ "\"%s\"\n", attrs[0],
+ slapi_sdn_get_dn(these_entries[i]));
+ }
+ /* Pull up the value set. */
+ if (slapi_vattr_values_get(entry, attrs[0], &values,
+ &disposition,
+ &actual_attr,
+ 0, &buffer_flags) != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: entry \"%s\" has no "
+ "values for \"%s\"\n",
+ slapi_sdn_get_dn(these_entries[i]),
+ attrs[0]);
+ slapi_entry_free(entry);
+ continue;
+ }
+ /* Walk the value set. */
+ for (j = slapi_valueset_first_value(values, &value);
+ j != -1;
+ j = slapi_valueset_next_value(values, j, &value)){
+ /* Get the value. */
+ bval = slapi_value_get_berval(value);
+ /* If the value is empty, skip it. */
+ if (bval->bv_len == 0) {
+ continue;
+ }
+ format_add_bv_list(&choices, bval);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referredx: found value "
+ "\"%.*s\" in \"%s\"\n",
+ bval->bv_len,
+ bval->bv_val,
+ slapi_sdn_get_dn(these_entries[i]));
+ }
+ slapi_vattr_values_free(&values, &actual_attr,
+ buffer_flags);
+ slapi_entry_free(entry);
+ }
+
+ /* Return any values we found. */
+ if (choices != NULL) {
+ format_add_choice(outbuf_choices, outbuf, choices);
+ format_free_bv_list(choices);
+ }
+
+ slapi_pblock_destroy(local_pb);
+ format_free_parsed_args(argv);
+
+ return 0;
+}
+
/* Evaluate each argument's list of results, after the first, in turn, and
* merge them, using the first argument as a separator. */
static int
@@ -1847,6 +2163,7 @@ format_lookup_fn(const char *fnname)
{"deref", format_deref},
{"derefx", format_derefx},
{"referred", format_referred},
+ {"referredx", format_referredx},
{"merge", format_merge},
{"match", format_match},
{"regmatch", format_regmatch},