diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-10-24 13:54:46 -0400 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-10-24 13:54:46 -0400 |
| commit | 316ece9f122d3ee63e84734cf4b790c691963e04 (patch) | |
| tree | 9f06d9ff8e13a68220d6d2e012d07338f7a005ca /src/format.c | |
| parent | af009c9d84d37ab5880f575efcddbae782fe64d1 (diff) | |
- add referredx, as derefx
Diffstat (limited to 'src/format.c')
| -rw-r--r-- | src/format.c | 319 |
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, + ¬e_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, + ¬e_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}, |
